activerecord-jdbc-adapter-ficoh 1.3.21-java

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.
Files changed (191) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +35 -0
  3. data/.travis.yml +462 -0
  4. data/.yardopts +4 -0
  5. data/Appraisals +36 -0
  6. data/CONTRIBUTING.md +49 -0
  7. data/Gemfile +68 -0
  8. data/History.md +1191 -0
  9. data/LICENSE.txt +25 -0
  10. data/README.md +277 -0
  11. data/RUNNING_TESTS.md +88 -0
  12. data/Rakefile +298 -0
  13. data/Rakefile.jdbc +20 -0
  14. data/activerecord-jdbc-adapter.gemspec +63 -0
  15. data/lib/active_record/connection_adapters/as400_adapter.rb +2 -0
  16. data/lib/active_record/connection_adapters/db2_adapter.rb +1 -0
  17. data/lib/active_record/connection_adapters/derby_adapter.rb +1 -0
  18. data/lib/active_record/connection_adapters/firebird_adapter.rb +1 -0
  19. data/lib/active_record/connection_adapters/h2_adapter.rb +1 -0
  20. data/lib/active_record/connection_adapters/hsqldb_adapter.rb +1 -0
  21. data/lib/active_record/connection_adapters/informix_adapter.rb +1 -0
  22. data/lib/active_record/connection_adapters/jdbc_adapter.rb +1 -0
  23. data/lib/active_record/connection_adapters/jndi_adapter.rb +1 -0
  24. data/lib/active_record/connection_adapters/mariadb_adapter.rb +1 -0
  25. data/lib/active_record/connection_adapters/mssql_adapter.rb +1 -0
  26. data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -0
  27. data/lib/active_record/connection_adapters/mysql_adapter.rb +1 -0
  28. data/lib/active_record/connection_adapters/oracle_adapter.rb +1 -0
  29. data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -0
  30. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -0
  31. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +1 -0
  32. data/lib/activerecord-jdbc-adapter.rb +1 -0
  33. data/lib/arel/visitors/compat.rb +64 -0
  34. data/lib/arel/visitors/db2.rb +137 -0
  35. data/lib/arel/visitors/derby.rb +112 -0
  36. data/lib/arel/visitors/firebird.rb +79 -0
  37. data/lib/arel/visitors/h2.rb +25 -0
  38. data/lib/arel/visitors/hsqldb.rb +32 -0
  39. data/lib/arel/visitors/postgresql_jdbc.rb +6 -0
  40. data/lib/arel/visitors/sql_server.rb +225 -0
  41. data/lib/arel/visitors/sql_server/ng42.rb +293 -0
  42. data/lib/arjdbc.rb +22 -0
  43. data/lib/arjdbc/db2.rb +4 -0
  44. data/lib/arjdbc/db2/adapter.rb +802 -0
  45. data/lib/arjdbc/db2/as400.rb +137 -0
  46. data/lib/arjdbc/db2/column.rb +177 -0
  47. data/lib/arjdbc/db2/connection_methods.rb +45 -0
  48. data/lib/arjdbc/derby.rb +3 -0
  49. data/lib/arjdbc/derby/active_record_patch.rb +13 -0
  50. data/lib/arjdbc/derby/adapter.rb +567 -0
  51. data/lib/arjdbc/derby/connection_methods.rb +16 -0
  52. data/lib/arjdbc/derby/schema_creation.rb +15 -0
  53. data/lib/arjdbc/discover.rb +104 -0
  54. data/lib/arjdbc/firebird.rb +4 -0
  55. data/lib/arjdbc/firebird/adapter.rb +468 -0
  56. data/lib/arjdbc/firebird/connection_methods.rb +20 -0
  57. data/lib/arjdbc/h2.rb +3 -0
  58. data/lib/arjdbc/h2/adapter.rb +335 -0
  59. data/lib/arjdbc/h2/connection_methods.rb +22 -0
  60. data/lib/arjdbc/hsqldb.rb +3 -0
  61. data/lib/arjdbc/hsqldb/adapter.rb +304 -0
  62. data/lib/arjdbc/hsqldb/connection_methods.rb +23 -0
  63. data/lib/arjdbc/hsqldb/explain_support.rb +35 -0
  64. data/lib/arjdbc/hsqldb/schema_creation.rb +11 -0
  65. data/lib/arjdbc/informix.rb +5 -0
  66. data/lib/arjdbc/informix/adapter.rb +160 -0
  67. data/lib/arjdbc/informix/connection_methods.rb +9 -0
  68. data/lib/arjdbc/jdbc.rb +62 -0
  69. data/lib/arjdbc/jdbc/adapter.rb +997 -0
  70. data/lib/arjdbc/jdbc/adapter_require.rb +46 -0
  71. data/lib/arjdbc/jdbc/arel_support.rb +149 -0
  72. data/lib/arjdbc/jdbc/base_ext.rb +34 -0
  73. data/lib/arjdbc/jdbc/callbacks.rb +52 -0
  74. data/lib/arjdbc/jdbc/column.rb +83 -0
  75. data/lib/arjdbc/jdbc/connection.rb +26 -0
  76. data/lib/arjdbc/jdbc/connection_methods.rb +59 -0
  77. data/lib/arjdbc/jdbc/driver.rb +44 -0
  78. data/lib/arjdbc/jdbc/error.rb +75 -0
  79. data/lib/arjdbc/jdbc/extension.rb +69 -0
  80. data/lib/arjdbc/jdbc/java.rb +13 -0
  81. data/lib/arjdbc/jdbc/type_cast.rb +154 -0
  82. data/lib/arjdbc/jdbc/type_converter.rb +142 -0
  83. data/lib/arjdbc/mssql.rb +7 -0
  84. data/lib/arjdbc/mssql/adapter.rb +822 -0
  85. data/lib/arjdbc/mssql/column.rb +207 -0
  86. data/lib/arjdbc/mssql/connection_methods.rb +72 -0
  87. data/lib/arjdbc/mssql/explain_support.rb +99 -0
  88. data/lib/arjdbc/mssql/limit_helpers.rb +231 -0
  89. data/lib/arjdbc/mssql/lock_methods.rb +77 -0
  90. data/lib/arjdbc/mssql/types.rb +343 -0
  91. data/lib/arjdbc/mssql/utils.rb +82 -0
  92. data/lib/arjdbc/mysql.rb +3 -0
  93. data/lib/arjdbc/mysql/adapter.rb +998 -0
  94. data/lib/arjdbc/mysql/bulk_change_table.rb +150 -0
  95. data/lib/arjdbc/mysql/column.rb +167 -0
  96. data/lib/arjdbc/mysql/connection_methods.rb +137 -0
  97. data/lib/arjdbc/mysql/explain_support.rb +82 -0
  98. data/lib/arjdbc/mysql/schema_creation.rb +58 -0
  99. data/lib/arjdbc/oracle.rb +4 -0
  100. data/lib/arjdbc/oracle/adapter.rb +968 -0
  101. data/lib/arjdbc/oracle/column.rb +136 -0
  102. data/lib/arjdbc/oracle/connection_methods.rb +21 -0
  103. data/lib/arjdbc/postgresql.rb +3 -0
  104. data/lib/arjdbc/postgresql/_bc_time_cast_patch.rb +21 -0
  105. data/lib/arjdbc/postgresql/adapter.rb +1498 -0
  106. data/lib/arjdbc/postgresql/base/array_parser.rb +95 -0
  107. data/lib/arjdbc/postgresql/base/oid.rb +412 -0
  108. data/lib/arjdbc/postgresql/base/pgconn.rb +8 -0
  109. data/lib/arjdbc/postgresql/base/schema_definitions.rb +132 -0
  110. data/lib/arjdbc/postgresql/column.rb +640 -0
  111. data/lib/arjdbc/postgresql/connection_methods.rb +44 -0
  112. data/lib/arjdbc/postgresql/explain_support.rb +53 -0
  113. data/lib/arjdbc/postgresql/oid/bytea.rb +3 -0
  114. data/lib/arjdbc/postgresql/oid_types.rb +265 -0
  115. data/lib/arjdbc/postgresql/schema_creation.rb +60 -0
  116. data/lib/arjdbc/railtie.rb +11 -0
  117. data/lib/arjdbc/sqlite3.rb +3 -0
  118. data/lib/arjdbc/sqlite3/adapter.rb +654 -0
  119. data/lib/arjdbc/sqlite3/connection_methods.rb +36 -0
  120. data/lib/arjdbc/sqlite3/explain_support.rb +29 -0
  121. data/lib/arjdbc/sybase.rb +2 -0
  122. data/lib/arjdbc/sybase/adapter.rb +47 -0
  123. data/lib/arjdbc/tasks.rb +13 -0
  124. data/lib/arjdbc/tasks/database_tasks.rb +66 -0
  125. data/lib/arjdbc/tasks/databases.rake +91 -0
  126. data/lib/arjdbc/tasks/databases3.rake +239 -0
  127. data/lib/arjdbc/tasks/databases4.rake +39 -0
  128. data/lib/arjdbc/tasks/db2_database_tasks.rb +104 -0
  129. data/lib/arjdbc/tasks/derby_database_tasks.rb +95 -0
  130. data/lib/arjdbc/tasks/h2_database_tasks.rb +31 -0
  131. data/lib/arjdbc/tasks/hsqldb_database_tasks.rb +70 -0
  132. data/lib/arjdbc/tasks/jdbc_database_tasks.rb +169 -0
  133. data/lib/arjdbc/tasks/mssql_database_tasks.rb +46 -0
  134. data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +297 -0
  135. data/lib/arjdbc/tasks/oracle_database_tasks.rb +65 -0
  136. data/lib/arjdbc/util/quoted_cache.rb +60 -0
  137. data/lib/arjdbc/util/serialized_attributes.rb +98 -0
  138. data/lib/arjdbc/util/table_copier.rb +108 -0
  139. data/lib/arjdbc/version.rb +8 -0
  140. data/lib/generators/jdbc/USAGE +9 -0
  141. data/lib/generators/jdbc/jdbc_generator.rb +17 -0
  142. data/pom.xml +285 -0
  143. data/rails_generators/jdbc_generator.rb +15 -0
  144. data/rails_generators/templates/config/initializers/jdbc.rb +10 -0
  145. data/rails_generators/templates/lib/tasks/jdbc.rake +11 -0
  146. data/rakelib/01-tomcat.rake +51 -0
  147. data/rakelib/02-test.rake +151 -0
  148. data/rakelib/bundler_ext.rb +11 -0
  149. data/rakelib/db.rake +58 -0
  150. data/rakelib/rails.rake +77 -0
  151. data/src/java/arjdbc/ArJdbcModule.java +288 -0
  152. data/src/java/arjdbc/db2/DB2Module.java +77 -0
  153. data/src/java/arjdbc/db2/DB2RubyJdbcConnection.java +128 -0
  154. data/src/java/arjdbc/derby/DerbyModule.java +180 -0
  155. data/src/java/arjdbc/derby/DerbyRubyJdbcConnection.java +153 -0
  156. data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +190 -0
  157. data/src/java/arjdbc/h2/H2Module.java +50 -0
  158. data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +86 -0
  159. data/src/java/arjdbc/hsqldb/HSQLDBModule.java +74 -0
  160. data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +76 -0
  161. data/src/java/arjdbc/jdbc/AdapterJavaService.java +43 -0
  162. data/src/java/arjdbc/jdbc/Callable.java +44 -0
  163. data/src/java/arjdbc/jdbc/ConnectionFactory.java +77 -0
  164. data/src/java/arjdbc/jdbc/DataSourceConnectionFactory.java +156 -0
  165. data/src/java/arjdbc/jdbc/DriverConnectionFactory.java +63 -0
  166. data/src/java/arjdbc/jdbc/DriverWrapper.java +128 -0
  167. data/src/java/arjdbc/jdbc/JdbcConnectionFactory.java +32 -0
  168. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +4541 -0
  169. data/src/java/arjdbc/jdbc/SQLBlock.java +54 -0
  170. data/src/java/arjdbc/jdbc/WithResultSet.java +37 -0
  171. data/src/java/arjdbc/mssql/MSSQLModule.java +91 -0
  172. data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +193 -0
  173. data/src/java/arjdbc/mysql/MySQLModule.java +140 -0
  174. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +456 -0
  175. data/src/java/arjdbc/oracle/OracleModule.java +81 -0
  176. data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +477 -0
  177. data/src/java/arjdbc/postgresql/ByteaUtils.java +171 -0
  178. data/src/java/arjdbc/postgresql/DriverImplementation.java +78 -0
  179. data/src/java/arjdbc/postgresql/PGDriverImplementation.java +535 -0
  180. data/src/java/arjdbc/postgresql/PostgreSQLModule.java +189 -0
  181. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +489 -0
  182. data/src/java/arjdbc/sqlite3/SQLite3Module.java +93 -0
  183. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +405 -0
  184. data/src/java/arjdbc/util/CallResultSet.java +826 -0
  185. data/src/java/arjdbc/util/DateTimeUtils.java +517 -0
  186. data/src/java/arjdbc/util/NumberUtils.java +50 -0
  187. data/src/java/arjdbc/util/ObjectSupport.java +65 -0
  188. data/src/java/arjdbc/util/QuotingUtils.java +139 -0
  189. data/src/java/arjdbc/util/StringCache.java +60 -0
  190. data/src/java/arjdbc/util/StringHelper.java +155 -0
  191. metadata +288 -0
@@ -0,0 +1,23 @@
1
+ ArJdbc::ConnectionMethods.module_eval do
2
+ def hsqldb_connection(config)
3
+ config[:adapter_spec] ||= ::ArJdbc::HSQLDB
4
+ config[:adapter_class] = ActiveRecord::ConnectionAdapters::HsqldbAdapter unless config.key?(:adapter_class)
5
+
6
+ return jndi_connection(config) if jndi_config?(config)
7
+
8
+ ArJdbc.load_driver(:HSQLDB) unless config[:load_driver] == false
9
+ config[:driver] ||= 'org.hsqldb.jdbcDriver'
10
+ config[:url] ||= begin
11
+ db = config[:database]
12
+ if db[0, 4] == 'mem:' || db[0, 5] == 'file:' || db[0, 5] == 'hsql:'
13
+ "jdbc:hsqldb:#{db}"
14
+ else
15
+ "jdbc:hsqldb:file:#{db}"
16
+ end
17
+ end
18
+ config[:connection_alive_sql] ||= 'CALL PI()' # does not like 'SELECT 1'
19
+
20
+ embedded_driver(config)
21
+ end
22
+ alias_method :jdbchsqldb_connection, :hsqldb_connection
23
+ end
@@ -0,0 +1,35 @@
1
+ module ArJdbc
2
+ module HSQLDB
3
+ module ExplainSupport
4
+ def supports_explain?; true; end
5
+
6
+ def explain(arel, binds = [])
7
+ sql = "EXPLAIN PLAN FOR #{to_sql(arel, binds)}"
8
+ raw_result = exec_query_raw(sql, "EXPLAIN", binds)
9
+ # HSQLDB's SqlTool just prints it as it comes :
10
+ #
11
+ # sql> EXPLAIN PLAN FOR SELECT * FROM entries JOIN users on ... ;
12
+ #
13
+ # isDistinctSelect=[false]
14
+ # isGrouped=[false]
15
+ # isAggregated=[false]
16
+ # columns=[ COLUMN: PUBLIC.ENTRIES.ID
17
+ # not nullable COLUMN: PUBLIC.ENTRIES.TITLE
18
+ # nullable COLUMN: PUBLIC.ENTRIES.UPDATED_ON
19
+ # nullable COLUMN: PUBLIC.ENTRIES.CONTENT
20
+ # nullable COLUMN: PUBLIC.ENTRIES.RATING
21
+ # nullable COLUMN: PUBLIC.ENTRIES.USER_ID
22
+ # nullable COLUMN: PUBLIC.USERS.ID
23
+ # not nullable COLUMN: PUBLIC.USERS.LOGIN
24
+ # nullable
25
+ # ]
26
+ # ...
27
+ # PARAMETERS=[]
28
+ # SUBQUERIES[]
29
+ #
30
+ raw_result.map!(&:values)
31
+ raw_result.join("\n")
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,11 @@
1
+ module ArJdbc
2
+ module HSQLDB
3
+ # @private
4
+ SchemaCreation = ::ActiveRecord::ConnectionAdapters::AbstractAdapter::SchemaCreation
5
+
6
+ def schema_creation
7
+ SchemaCreation.new self
8
+ end
9
+
10
+ end
11
+ end if ::ActiveRecord::ConnectionAdapters::AbstractAdapter.const_defined? :SchemaCreation
@@ -0,0 +1,5 @@
1
+ require 'arjdbc'
2
+ ArJdbc.load_java_part :Informix
3
+ require 'arjdbc/informix/adapter'
4
+ require 'arjdbc/informix/connection_methods'
5
+ ArJdbc.warn_unsupported_adapter 'informix', [4, 2] # warns on AR >= 4.2
@@ -0,0 +1,160 @@
1
+ require 'arjdbc/util/serialized_attributes'
2
+
3
+ module ArJdbc
4
+ module Informix
5
+
6
+ @@_lob_callback_added = nil
7
+
8
+ def self.extended(base)
9
+ unless @@_lob_callback_added
10
+ ActiveRecord::Base.class_eval do
11
+ def after_save_with_informix_lob
12
+ lob_columns = self.class.columns.select { |c| [:text, :binary].include?(c.type) }
13
+ lob_columns.each do |column|
14
+ value = Util::SerializedAttributes.dump_column_value(self, column)
15
+ next if value.nil? || (value == '')
16
+
17
+ connection.write_large_object(
18
+ column.type == :binary, column.name,
19
+ self.class.table_name, self.class.primary_key,
20
+ quote_value(id), value
21
+ )
22
+ end
23
+ end
24
+ end
25
+
26
+ ActiveRecord::Base.after_save :after_save_with_informix_lob
27
+ @@_lob_callback_added = true
28
+ end
29
+ end
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
+ JdbcConnection = ::ActiveRecord::ConnectionAdapters::InformixJdbcConnection
37
+
38
+ # @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_connection_class
39
+ def self.jdbc_connection_class; JdbcConnection end
40
+
41
+ # @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_column_class
42
+ def jdbc_column_class
43
+ ::ActiveRecord::ConnectionAdapters::InformixColumn
44
+ end
45
+
46
+ module ColumnMethods
47
+
48
+ private
49
+ # TODO: Test all Informix column types.
50
+ def simplified_type(field_type)
51
+ if field_type =~ /serial/i
52
+ :primary_key
53
+ else
54
+ super
55
+ end
56
+ end
57
+
58
+ end
59
+
60
+ def modify_types(types)
61
+ super(types)
62
+ types[:primary_key] = "SERIAL PRIMARY KEY"
63
+ types[:string] = { :name => "VARCHAR", :limit => 255 }
64
+ types[:integer] = { :name => "INTEGER" }
65
+ types[:float] = { :name => "FLOAT" }
66
+ types[:decimal] = { :name => "DECIMAL" }
67
+ types[:datetime] = { :name => "DATETIME YEAR TO FRACTION(5)" }
68
+ types[:timestamp] = { :name => "DATETIME YEAR TO FRACTION(5)" }
69
+ types[:time] = { :name => "DATETIME HOUR TO FRACTION(5)" }
70
+ types[:date] = { :name => "DATE" }
71
+ types[:binary] = { :name => "BYTE" }
72
+ types[:boolean] = { :name => "BOOLEAN" }
73
+ types
74
+ end
75
+
76
+ def prefetch_primary_key?(table_name = nil)
77
+ true
78
+ end
79
+
80
+ def supports_migrations?
81
+ true
82
+ end
83
+
84
+ def default_sequence_name(table, column)
85
+ "#{table}_seq"
86
+ end
87
+
88
+ def add_limit_offset!(sql, options)
89
+ if options[:limit]
90
+ limit = "FIRST #{options[:limit]}" # SKIP available only in IDS >= 10 :
91
+ offset = (db_major_version >= 10 && options[:offset] ? "SKIP #{options[:offset]}" : "")
92
+ sql.sub!(/^\s*?select /i, "SELECT #{offset} #{limit} ")
93
+ end
94
+ sql
95
+ end
96
+
97
+ def next_sequence_value(sequence_name)
98
+ select_one("SELECT #{sequence_name}.nextval id FROM systables WHERE tabid=1")['id']
99
+ end
100
+
101
+ # TODO: Add some smart quoting for newlines in string and text fields.
102
+ def quote_string(string)
103
+ string.gsub(/\'/, "''")
104
+ end
105
+
106
+ def quote(value, column = nil)
107
+ column_type = column && column.type
108
+ if column_type == :binary || column_type == :text
109
+ # LOBs are updated separately by an after_save trigger.
110
+ "NULL"
111
+ elsif column_type == :date
112
+ "'#{value.mon}/#{value.day}/#{value.year}'"
113
+ else
114
+ super
115
+ end
116
+ end
117
+
118
+ def create_table(name, options = {})
119
+ super(name, options)
120
+ execute("CREATE SEQUENCE #{name}_seq")
121
+ end
122
+
123
+ def rename_table(name, new_name)
124
+ execute("RENAME TABLE #{name} TO #{new_name}")
125
+ execute("RENAME SEQUENCE #{name}_seq TO #{new_name}_seq")
126
+ end
127
+
128
+ def drop_table(name)
129
+ super(name)
130
+ execute("DROP SEQUENCE #{name}_seq")
131
+ end
132
+
133
+ def remove_index(table_name, options = {})
134
+ @connection.execute_update("DROP INDEX #{index_name(table_name, options)}")
135
+ end
136
+
137
+ def select(sql, *rest)
138
+ # Informix does not like "= NULL", "!= NULL", or "<> NULL".
139
+ super(sql.gsub(/(!=|<>)\s*null/i, "IS NOT NULL").gsub(/=\s*null/i, "IS NULL"), *rest)
140
+ end
141
+
142
+ private
143
+
144
+ def db_major_version
145
+ @@db_major_version ||=
146
+ select_one("SELECT dbinfo('version', 'major') version FROM systables WHERE tabid = 1")['version'].to_i
147
+ end
148
+
149
+ end # module Informix
150
+ end # module ::ArJdbc
151
+
152
+ module ActiveRecord::ConnectionAdapters
153
+ class InformixColumn < JdbcColumn
154
+ include ::ArJdbc::Informix::ColumnMethods
155
+ end
156
+
157
+ class InformixAdapter < JdbcAdapter
158
+ include ::ArJdbc::Informix
159
+ end
160
+ end
@@ -0,0 +1,9 @@
1
+ ArJdbc::ConnectionMethods.module_eval do
2
+ def informix_connection(config)
3
+ config[:port] ||= 9088
4
+ config[:url] ||= "jdbc:informix-sqli://#{config[:host]}:#{config[:port]}/#{config[:database]}:INFORMIXSERVER=#{config[:servername]}"
5
+ config[:driver] = 'com.informix.jdbc.IfxDriver'
6
+ config[:adapter_spec] = ::ArJdbc::Informix
7
+ jdbc_connection(config)
8
+ end
9
+ end
@@ -0,0 +1,62 @@
1
+ require 'active_support/deprecation'
2
+
3
+ module ArJdbc
4
+
5
+ # @private
6
+ AR40 = ::ActiveRecord::VERSION::MAJOR > 3
7
+ # @private
8
+ AR42 = ::ActiveRecord::VERSION::STRING >= '4.2'
9
+ # @private
10
+ AR50 = ::ActiveRecord::VERSION::MAJOR > 4
11
+
12
+ class << self
13
+
14
+ # @private Internal API
15
+ def warn_unsupported_adapter(adapter, version = nil)
16
+ warn_prefix = 'NOTE:'
17
+ if version # e.g. [4, 2]
18
+ ar_version = [ ActiveRecord::VERSION::MAJOR, ActiveRecord::VERSION::MINOR, ActiveRecord::VERSION::TINY ]
19
+ if ( ar_version <=> version ) >= 0 # e.g. 4.2.0 > 4.2
20
+ warn_prefix = "NOTE: ActiveRecord #{version.join('.')} with"
21
+ else
22
+ warn_prefix = nil
23
+ end
24
+ end
25
+ warn "#{warn_prefix} adapter: #{adapter} is not (yet) fully supported by AR-JDBC," <<
26
+ " please consider helping us out." if warn_prefix
27
+ end
28
+
29
+ def warn(message, once = nil)
30
+ super("WARNING: #{message}") || true if warn?(message, once)
31
+ end
32
+
33
+ def deprecate(message, once = nil) # adds a "DEPRECATION WARNING: " prefix
34
+ if warn?(message, once)
35
+ callstack = once.is_a?(Integer) ? caller(once) : caller
36
+ ::ActiveSupport::Deprecation.warn(message, callstack) || true
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ @@warns = nil
43
+ @@warns = false if ENV_JAVA['arjdbc.warn'].eql? 'false'
44
+
45
+ def warn?(message, once)
46
+ return nil if @@warns.equal?(false) || ! message
47
+ warns = @@warns ||= ( require 'set'; Set.new )
48
+ return false if warns.include?(message)
49
+ warns << message.dup if once
50
+ true
51
+ end
52
+
53
+ end
54
+
55
+ require 'arjdbc/jdbc/adapter'
56
+
57
+ if ENV_JAVA['arjdbc.extensions.discover'].eql? 'true'
58
+ self.discover_extensions
59
+ else
60
+ require 'arjdbc/discover'
61
+ end
62
+ end
@@ -0,0 +1,997 @@
1
+ require 'active_record/version'
2
+ require 'active_record/connection_adapters/abstract_adapter'
3
+
4
+ require 'arjdbc/version'
5
+ require 'arjdbc/jdbc/java'
6
+ require 'arjdbc/jdbc/base_ext'
7
+ require 'arjdbc/jdbc/error'
8
+ require 'arjdbc/jdbc/connection_methods'
9
+ require 'arjdbc/jdbc/column'
10
+ require 'arjdbc/jdbc/connection'
11
+ require 'arjdbc/jdbc/arel_support'
12
+ require 'arjdbc/jdbc/callbacks'
13
+ require 'arjdbc/jdbc/extension'
14
+
15
+ module ActiveRecord
16
+ module ConnectionAdapters
17
+
18
+ autoload :JdbcDriver, 'arjdbc/jdbc/driver' # compatibility - no longer used
19
+ autoload :JdbcTypeConverter, 'arjdbc/jdbc/type_converter'
20
+
21
+ # Built on top of `ActiveRecord::ConnectionAdapters::AbstractAdapter` which
22
+ # provides the abstract interface for database-specific functionality, this
23
+ # class serves 2 purposes in AR-JDBC :
24
+ # - as a base class for sub-classes
25
+ # - usable standalone (or with a mixed in adapter spec module)
26
+ #
27
+ # Historically this class is mostly been used standalone and that's still a
28
+ # valid use-case esp. since (with it's `arjdbc.jdbc.RubyJdbcConnectionClass`)
29
+ # JDBC provides a unified interface for all databases in Java it tries to do
30
+ # it's best implementing all `ActiveRecord` functionality on top of that.
31
+ # This might no be perfect that's why it checks for a `config[:adapter_spec]`
32
+ # module (or tries to resolve one from the JDBC driver's meta-data) and if
33
+ # the database has "extended" AR-JDBC support mixes in the given module for
34
+ # each adapter instance.
35
+ # This is sufficient for most database specific specs we support, but for
36
+ # compatibility with native (MRI) adapters it's perfectly fine to sub-class
37
+ # the adapter and override some of its API methods.
38
+ class JdbcAdapter < AbstractAdapter
39
+ extend ShadowCoreMethods
40
+
41
+ include Jdbc::ArelSupport
42
+ include Jdbc::ConnectionPoolCallbacks
43
+
44
+ attr_reader :config
45
+
46
+ def self.new(connection, logger = nil, pool = nil)
47
+ adapter = super
48
+ Jdbc::JndiConnectionPoolCallbacks.prepare(adapter, adapter.instance_variable_get(:@connection))
49
+ adapter
50
+ end
51
+
52
+ # Initializes the (JDBC connection) adapter instance.
53
+ # The passed configuration Hash's keys are symbolized, thus changes to
54
+ # the original `config` keys won't be reflected in the adapter.
55
+ # If the adapter's sub-class or the spec module that this instance will
56
+ # extend in responds to `configure_connection` than it will be called.
57
+ # @param connection an (optional) connection instance
58
+ # @param logger the `ActiveRecord::Base.logger` to use (or nil)
59
+ # @param config the database configuration
60
+ # @note `initialize(logger, config)` with 2 arguments is supported as well
61
+ def initialize(connection, logger, config = nil); pool = nil
62
+ if config.nil?
63
+ if logger.respond_to?(:key?) # (logger, config)
64
+ config, logger, connection = logger, connection, nil
65
+ else
66
+ config = connection.respond_to?(:config) ?
67
+ connection.config : ActiveRecord::Base.connection_pool.spec.config
68
+ end
69
+ elsif config.respond_to?(:spec) && config.respond_to?(:connection)
70
+ pool = config; config = pool.spec.config # AR >= 3.2 compatibility
71
+ end
72
+
73
+ @config = config.respond_to?(:symbolize_keys) ? config.symbolize_keys : config
74
+
75
+ if self.class.equal? JdbcAdapter
76
+ spec = @config.key?(:adapter_spec) ? @config[:adapter_spec] :
77
+ ( @config[:adapter_spec] = adapter_spec(@config) ) # due resolving visitor
78
+ extend spec if spec
79
+ end
80
+
81
+ # NOTE: adapter spec's init_connection only called if instantiated here :
82
+ connection ||= jdbc_connection_class(spec).new(@config, self)
83
+
84
+ pool.nil? ? super(connection, logger) : super(connection, logger, pool)
85
+
86
+ connection.configure_connection # will call us (maybe)
87
+
88
+ @visitor = new_visitor # nil if no AREL (AR-2.3)
89
+ end
90
+
91
+ # By convention sub-adapters are expected to export a JDBC connection
92
+ # type they wish the adapter instantiates on {#initialize} by default.
93
+ # @since 1.4.0
94
+ JdbcConnection = ::ActiveRecord::ConnectionAdapters::JdbcConnection
95
+
96
+ # Returns the (JDBC) connection class to be used for this adapter.
97
+ # This is used by (database specific) spec modules to override the class
98
+ # used assuming some of the available methods have been re-defined.
99
+ # @see ActiveRecord::ConnectionAdapters::JdbcConnection
100
+ def self.jdbc_connection_class(spec)
101
+ connection_class = spec.jdbc_connection_class if spec && spec.respond_to?(:jdbc_connection_class)
102
+ connection_class ? connection_class : self::JdbcConnection
103
+ end
104
+
105
+ # @note The spec argument passed is ignored and shall no longer be used.
106
+ # @see ActiveRecord::ConnectionAdapters::JdbcConnection#jdbc_connection_class
107
+ def jdbc_connection_class(spec = nil)
108
+ spec ? self.class.jdbc_connection_class(spec) : self.class::JdbcConnection
109
+ end
110
+
111
+ # Returns the (JDBC) `ActiveRecord` column class for this adapter.
112
+ # This is used by (database specific) spec modules to override the class.
113
+ # @see ActiveRecord::ConnectionAdapters::JdbcColumn
114
+ def jdbc_column_class
115
+ return self.class::Column if self.class.const_defined?(:Column)
116
+ ::ActiveRecord::ConnectionAdapters::JdbcColumn # TODO auto-load
117
+ end
118
+
119
+ # @private Simple fix for keeping 1.8 compatibility.
120
+ def jdbc_column_class
121
+ column = self.class::Column rescue nil
122
+ return column if column
123
+ ::ActiveRecord::ConnectionAdapters::JdbcColumn # TODO auto-load
124
+ end if RUBY_VERSION < '1.9'
125
+
126
+ # Retrieve the raw `java.sql.Connection` object.
127
+ # The unwrap parameter is useful if an attempt to unwrap a pooled (JNDI)
128
+ # connection should be made - to really return the 'native' JDBC object.
129
+ # @param unwrap [true, false] whether to unwrap the connection object
130
+ # @return [Java::JavaSql::Connection] the JDBC connection
131
+ def jdbc_connection(unwrap = nil)
132
+ raw_connection.jdbc_connection(unwrap)
133
+ end
134
+
135
+ # Locate the specialized (database specific) adapter specification module
136
+ # if one exists based on provided configuration data. This module will than
137
+ # extend an instance of the adapter (unless an `:adapter_class` provided).
138
+ #
139
+ # This method is called during {#initialize} unless an explicit
140
+ # `config[:adapter_spec]` is set.
141
+ # @param config the configuration to check for `:adapter_spec`
142
+ # @return [Module] the database specific module
143
+ def adapter_spec(config)
144
+ dialect = ( config[:dialect] || config[:driver] ).to_s
145
+ ::ArJdbc.modules.each do |constant| # e.g. ArJdbc::MySQL
146
+ if constant.respond_to?(:adapter_matcher)
147
+ spec = constant.adapter_matcher(dialect, config)
148
+ return spec if spec
149
+ end
150
+ end
151
+
152
+ unless config.key?(:dialect)
153
+ begin # does nothing unless config[:jndi] || config[:data_source]
154
+ dialect = ::ArJdbc.with_meta_data_from_data_source_if_any(config) do
155
+ |meta_data| config[:dialect] = meta_data.getDatabaseProductName
156
+ end
157
+ return adapter_spec(config) if dialect # re-try matching with :dialect
158
+ rescue => e
159
+ ::ArJdbc.warn("failed to set :dialect from database meda-data: #{e}")
160
+ end
161
+ end
162
+
163
+ nil
164
+ end
165
+
166
+ ADAPTER_NAME = 'JDBC'.freeze
167
+
168
+ # @return [String] the 'JDBC' adapter name.
169
+ def adapter_name
170
+ ADAPTER_NAME
171
+ end
172
+
173
+ # Will return true even when native adapter classes passed in
174
+ # e.g. `jdbc_adapter.is_a? ConnectionAdapter::PostgresqlAdapter`
175
+ #
176
+ # This is only necessary (for built-in adapters) when
177
+ # `config[:adapter_class]` is forced to `nil` and the `:adapter_spec`
178
+ # module is used to extend the `JdbcAdapter`, otherwise we replace the
179
+ # class constants for built-in adapters (MySQL, PostgreSQL and SQLite3).
180
+ # @override
181
+ # @private
182
+ def is_a?(klass)
183
+ # This is to fake out current_adapter? conditional logic in AR tests
184
+ if klass.is_a?(Class) && klass.name =~ /#{adapter_name}Adapter$/i
185
+ true
186
+ else
187
+ super
188
+ end
189
+ end
190
+
191
+ # If there's a `self.arel2_visitors(config)` method on the adapter
192
+ # spec than it is preferred and will be used instead of this one.
193
+ # @return [Hash] the AREL visitor to use
194
+ # @deprecated No longer used.
195
+ # @see ActiveRecord::ConnectionAdapters::Jdbc::ArelSupport
196
+ def self.arel2_visitors(config)
197
+ { 'jdbc' => ::Arel::Visitors::ToSql }
198
+ end
199
+
200
+ # @see ActiveRecord::ConnectionAdapters::JdbcAdapter#arel2_visitors
201
+ # @deprecated No longer used.
202
+ def self.configure_arel2_visitors(config)
203
+ visitors = ::Arel::Visitors::VISITORS
204
+ klass = config[:adapter_spec]
205
+ klass = self unless klass.respond_to?(:arel2_visitors)
206
+ visitor = nil
207
+ klass.arel2_visitors(config).each do |name, arel|
208
+ visitors[name] = ( visitor = arel )
209
+ end
210
+ if visitor && config[:adapter] =~ /^(jdbc|jndi)$/
211
+ visitors[ config[:adapter] ] = visitor
212
+ end
213
+ visitor
214
+ end
215
+
216
+ # DB specific types are detected but adapter specs (or extenders) are
217
+ # expected to hand tune these types for concrete databases.
218
+ # @return [Hash] the native database types
219
+ # @override
220
+ def native_database_types
221
+ @native_database_types ||= begin
222
+ types = @connection.native_database_types
223
+ modify_types(types)
224
+ types
225
+ end
226
+ end
227
+
228
+ # @override introduced in AR 4.2
229
+ def valid_type?(type)
230
+ ! native_database_types[type].nil?
231
+ end
232
+
233
+ # Allows for modification of the detected native types.
234
+ # @param types the resolved native database types
235
+ # @see #native_database_types
236
+ def modify_types(types)
237
+ types
238
+ end
239
+
240
+ # Abstract adapter default implementation does nothing silently.
241
+ # @override
242
+ def structure_dump
243
+ raise NotImplementedError, "structure_dump not supported"
244
+ end
245
+
246
+ # JDBC adapters support migration.
247
+ # @return [true]
248
+ # @override
249
+ def supports_migrations?
250
+ true
251
+ end
252
+
253
+ # Returns the underlying database name.
254
+ # @override
255
+ def database_name
256
+ @connection.database_name
257
+ end
258
+
259
+ # @override
260
+ def active?
261
+ return false unless @connection
262
+ @connection.active?
263
+ end
264
+
265
+ # @override
266
+ def reconnect!
267
+ @connection.reconnect! # handles adapter.configure_connection
268
+ @connection
269
+ end
270
+
271
+ # @override
272
+ def disconnect!
273
+ @connection.disconnect! if @connection
274
+ end
275
+
276
+ # @override
277
+ #def verify!(*ignored)
278
+ # if @connection && @connection.jndi?
279
+ # # checkout call-back does #reconnect!
280
+ # else
281
+ # reconnect! unless active? # super
282
+ # end
283
+ #end
284
+
285
+ if ActiveRecord::VERSION::MAJOR < 3
286
+
287
+ # @private
288
+ def jdbc_insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
289
+ insert_sql(sql, name, pk, id_value, sequence_name)
290
+ end
291
+ alias_chained_method :insert, :query_dirty, :jdbc_insert
292
+
293
+ # @private
294
+ def jdbc_update(sql, name = nil, binds = [])
295
+ execute(sql, name, binds)
296
+ end
297
+ alias_chained_method :update, :query_dirty, :jdbc_update
298
+
299
+ # @private
300
+ def jdbc_select_all(sql, name = nil, binds = [])
301
+ select(sql, name, binds)
302
+ end
303
+ alias_chained_method :select_all, :query_cache, :jdbc_select_all
304
+
305
+ end
306
+
307
+ # @note Used on AR 2.3 and 3.0
308
+ # @override
309
+ def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
310
+ id = execute(sql, name)
311
+ id_value || id
312
+ end
313
+
314
+ def columns(table_name, name = nil)
315
+ @connection.columns(table_name.to_s)
316
+ end
317
+
318
+ # Starts a database transaction.
319
+ # @override
320
+ def begin_db_transaction
321
+ @connection.begin
322
+ end
323
+
324
+ # Commits the current database transaction.
325
+ # @override
326
+ def commit_db_transaction
327
+ @connection.commit
328
+ end
329
+
330
+ # Rolls back the current database transaction.
331
+ # @override
332
+ def rollback_db_transaction
333
+ @connection.rollback
334
+ end
335
+
336
+ # Starts a database transaction.
337
+ # @param isolation the transaction isolation to use
338
+ # @since 1.3.0
339
+ # @override on **AR-4.0**
340
+ def begin_isolated_db_transaction(isolation)
341
+ @connection.begin(isolation)
342
+ end
343
+
344
+ # Does this adapter support setting the isolation level for a transaction?
345
+ # Unlike 'plain' `ActiveRecord` we allow checking for concrete transaction
346
+ # isolation level support by the database.
347
+ # @param level optional to check if we support a specific isolation level
348
+ # @since 1.3.0
349
+ # @extension added optional level parameter
350
+ def supports_transaction_isolation?(level = nil)
351
+ @connection.supports_transaction_isolation?(level)
352
+ end
353
+
354
+ # Does our database (+ its JDBC driver) support save-points?
355
+ # @since 1.3.0
356
+ # @override
357
+ def supports_savepoints?
358
+ @connection.supports_savepoints?
359
+ end
360
+
361
+ # Creates a (transactional) save-point one can rollback to.
362
+ # Unlike 'plain' `ActiveRecord` it is allowed to pass a save-point name.
363
+ # @param name the save-point name
364
+ # @return save-point name (even if nil passed will be generated)
365
+ # @since 1.3.0
366
+ # @extension added optional name parameter
367
+ def create_savepoint(name = current_savepoint_name(true))
368
+ @connection.create_savepoint(name)
369
+ end
370
+
371
+ # Transaction rollback to a given (previously created) save-point.
372
+ # If no save-point name given rollback to the last created one.
373
+ # @param name the save-point name
374
+ # @since 1.3.0
375
+ # @extension added optional name parameter
376
+ def rollback_to_savepoint(name = current_savepoint_name(true))
377
+ @connection.rollback_savepoint(name)
378
+ end
379
+
380
+ # Release a previously created save-point.
381
+ # @note Save-points are auto-released with the transaction they're created
382
+ # in (on transaction commit or roll-back).
383
+ # @param name the save-point name
384
+ # @since 1.3.0
385
+ # @extension added optional name parameter
386
+ def release_savepoint(name = current_savepoint_name(false))
387
+ @connection.release_savepoint(name)
388
+ end
389
+
390
+ # Due tracking of save-points created in a LIFO manner, always returns
391
+ # the correct name if any (last) save-point has been marked and not released.
392
+ # Otherwise when creating a save-point same naming convention as
393
+ # `ActiveRecord` uses ("active_record_" prefix) will be returned.
394
+ # @return [String] the current save-point name
395
+ # @since 1.3.0
396
+ # @override
397
+ def current_savepoint_name(compat = true)
398
+ open_tx = open_transactions
399
+ return "active_record_#{open_tx}" if compat # by default behave like AR
400
+
401
+ sp_names = @connection.marked_savepoint_names
402
+ sp_names.last || "active_record_#{open_tx}"
403
+ # should (open_tx- 1) here but we play by AR's rules as it might fail
404
+ end unless ArJdbc::AR42
405
+
406
+ # @note Same as AR 4.2 but we're allowing an unused parameter.
407
+ # @private
408
+ def current_savepoint_name(compat = nil)
409
+ current_transaction.savepoint_name # unlike AR 3.2-4.1 might be nil
410
+ end if ArJdbc::AR42
411
+
412
+ # @override
413
+ def supports_views?
414
+ @connection.supports_views?
415
+ end
416
+
417
+ # AR-JDBC extension that allows you to have read-only connections.
418
+ # Read-only connection do not allow any inserts/updates, such operations fail.
419
+ # @return [Boolean] whether the underlying conn is read-only (false by default)
420
+ # @since 1.4.0
421
+ def read_only?
422
+ @connection.read_only?
423
+ end
424
+
425
+ # AR-JDBC extension that allows you to have read-only connections.
426
+ # @param flag the read-only flag to set
427
+ # @see #read_only?
428
+ # @since 1.4.0
429
+ def read_only=(flag)
430
+ @connection.read_only = flag
431
+ end
432
+
433
+ # Executes a SQL query in the context of this connection using the bind
434
+ # substitutes.
435
+ # @param sql the query string (or AREL object)
436
+ # @param name logging marker for the executed SQL statement log entry
437
+ # @param binds the bind parameters
438
+ # @return [ActiveRecord::Result] or [Array] on **AR-2.3**
439
+ # @override available since **AR-3.1**
440
+ def exec_query(sql, name = 'SQL', binds = [])
441
+ if sql.respond_to?(:to_sql)
442
+ sql = to_sql(sql, binds); to_sql = true
443
+ end
444
+ if prepared_statements?
445
+ log(sql, name, binds) { @connection.execute_query(sql, binds) }
446
+ else
447
+ sql = suble_binds(sql, binds) unless to_sql # deprecated behavior
448
+ log(sql, name) { @connection.execute_query(sql) }
449
+ end
450
+ end
451
+
452
+ # Executes an insert statement in the context of this connection.
453
+ # @param sql the query string (or AREL object)
454
+ # @param name logging marker for the executed SQL statement log entry
455
+ # @param binds the bind parameters
456
+ # @override available since **AR-3.1**
457
+ def exec_insert(sql, name, binds, pk = nil, sequence_name = nil)
458
+ if sql.respond_to?(:to_sql)
459
+ sql = to_sql(sql, binds); to_sql = true
460
+ end
461
+ if prepared_statements?
462
+ log(sql, name || 'SQL', binds) { @connection.execute_insert(sql, binds) }
463
+ else
464
+ sql = suble_binds(sql, binds) unless to_sql # deprecated behavior
465
+ log(sql, name || 'SQL') { @connection.execute_insert(sql) }
466
+ end
467
+ end
468
+
469
+ # Executes a delete statement in the context of this connection.
470
+ # @param sql the query string (or AREL object)
471
+ # @param name logging marker for the executed SQL statement log entry
472
+ # @param binds the bind parameters
473
+ # @override available since **AR-3.1**
474
+ def exec_delete(sql, name, binds)
475
+ if sql.respond_to?(:to_sql)
476
+ sql = to_sql(sql, binds); to_sql = true
477
+ end
478
+ if prepared_statements?
479
+ log(sql, name || 'SQL', binds) { @connection.execute_delete(sql, binds) }
480
+ else
481
+ sql = suble_binds(sql, binds) unless to_sql # deprecated behavior
482
+ log(sql, name || 'SQL') { @connection.execute_delete(sql) }
483
+ end
484
+ end
485
+
486
+ # # Executes an update statement in the context of this connection.
487
+ # @param sql the query string (or AREL object)
488
+ # @param name logging marker for the executed SQL statement log entry
489
+ # @param binds the bind parameters
490
+ # @override available since **AR-3.1**
491
+ def exec_update(sql, name, binds)
492
+ if sql.respond_to?(:to_sql)
493
+ sql = to_sql(sql, binds); to_sql = true
494
+ end
495
+ if prepared_statements?
496
+ log(sql, name || 'SQL', binds) { @connection.execute_update(sql, binds) }
497
+ else
498
+ sql = suble_binds(sql, binds) unless to_sql # deprecated behavior
499
+ log(sql, name || 'SQL') { @connection.execute_update(sql) }
500
+ end
501
+ end
502
+
503
+ # Similar to {#exec_query} except it returns "raw" results in an array
504
+ # where each rows is a hash with keys as columns (just like Rails used to
505
+ # do up until 3.0) instead of wrapping them in a {#ActiveRecord::Result}.
506
+ # @param sql the query string (or AREL object)
507
+ # @param name logging marker for the executed SQL statement log entry
508
+ # @param binds the bind parameters
509
+ # @yield [v1, v2] depending on the row values returned from the query
510
+ # In case a block is given it will yield each row from the result set
511
+ # instead of returning mapped query results in an array.
512
+ # @return [Array] unless a block is given
513
+ def exec_query_raw(sql, name = 'SQL', binds = [], &block)
514
+ if sql.respond_to?(:to_sql)
515
+ sql = to_sql(sql, binds); to_sql = true
516
+ end
517
+ if prepared_statements?
518
+ log(sql, name, binds) { @connection.execute_query_raw(sql, binds, &block) }
519
+ else
520
+ sql = suble_binds(sql, binds) unless to_sql # deprecated behavior
521
+ log(sql, name) { @connection.execute_query_raw(sql, &block) }
522
+ end
523
+ end
524
+
525
+ # @private
526
+ # @override
527
+ def select_rows(sql, name = nil, binds = [])
528
+ exec_query_raw(sql, name, binds).map!(&:values)
529
+ end
530
+
531
+ if ActiveRecord::VERSION::MAJOR > 3 # expects AR::Result e.g. from select_all
532
+
533
+ # @private
534
+ def select(sql, name = nil, binds = [])
535
+ exec_query(to_sql(sql, binds), name, binds)
536
+ end
537
+
538
+ else
539
+
540
+ # @private
541
+ def select(sql, name = nil, binds = []) # NOTE: only (sql, name) on AR < 3.1
542
+ exec_query_raw(to_sql(sql, binds), name, binds)
543
+ end
544
+
545
+ end
546
+
547
+ # Executes the SQL statement in the context of this connection.
548
+ # The return value from this method depends on the SQL type (whether
549
+ # it's a SELECT, INSERT etc.). For INSERTs a generated id might get
550
+ # returned while for UPDATE statements the affected row count.
551
+ # Please note that this method returns "raw" results (in an array) for
552
+ # statements that return a result set, while {#exec_query} is expected to
553
+ # return a `ActiveRecord::Result` (since AR 3.1).
554
+ # @note This method does not use prepared statements.
555
+ # @note The method does not emulate various "native" `execute` results on MRI.
556
+ # @see #exec_query
557
+ # @see #exec_insert
558
+ # @see #exec_update
559
+ def execute(sql, name = nil, binds = nil)
560
+ sql = suble_binds to_sql(sql, binds), binds if binds
561
+ if name == :skip_logging
562
+ _execute(sql, name)
563
+ else
564
+ log(sql, name) { _execute(sql, name) }
565
+ end
566
+ end
567
+
568
+ # @private documented above
569
+ def execute(sql, name = nil, skip_logging = false)
570
+ if skip_logging.is_a?(Array)
571
+ binds, skip_logging = skip_logging, false
572
+ sql = suble_binds to_sql(sql, binds), binds
573
+ end
574
+ if skip_logging || name == :skip_logging
575
+ _execute(sql, name)
576
+ else
577
+ log(sql, name) { _execute(sql, name) }
578
+ end
579
+ end if ActiveRecord::VERSION::MAJOR < 3 ||
580
+ ( ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR == 0 )
581
+
582
+ # We need to do it this way, to allow Rails stupid tests to always work
583
+ # even if we define a new `execute` method. Instead of mixing in a new
584
+ # `execute`, an `_execute` should be mixed in.
585
+ # @deprecated it was only introduced due tests
586
+ # @private
587
+ def _execute(sql, name = nil)
588
+ @connection.execute(sql)
589
+ end
590
+ private :_execute
591
+
592
+ # Kind of `execute(sql) rescue nil` but logging failures at debug level only.
593
+ def execute_quietly(sql, name = 'SQL')
594
+ log(sql, name) do
595
+ begin
596
+ _execute(sql)
597
+ rescue => e
598
+ logger.debug("#{e.class}: #{e.message}: #{sql}")
599
+ end
600
+ end
601
+ end
602
+
603
+ # @override
604
+ def tables(name = nil)
605
+ @connection.tables
606
+ end
607
+
608
+ # @override
609
+ def table_exists?(name)
610
+ return false unless name
611
+ @connection.table_exists?(name) # schema_name = nil
612
+ end
613
+
614
+ # @override
615
+ def data_sources
616
+ tables
617
+ end if ArJdbc::AR42
618
+
619
+ # @override
620
+ def data_source_exists?(name)
621
+ table_exists?(name)
622
+ end if ArJdbc::AR42
623
+
624
+ # @override
625
+ def indexes(table_name, name = nil, schema_name = nil)
626
+ @connection.indexes(table_name, name, schema_name)
627
+ end
628
+
629
+ # @override
630
+ def pk_and_sequence_for(table)
631
+ ( key = primary_key(table) ) ? [ key, nil ] : nil
632
+ end
633
+
634
+ # @override
635
+ def primary_key(table)
636
+ primary_keys(table).first
637
+ end
638
+
639
+ # @override
640
+ def primary_keys(table)
641
+ @connection.primary_keys(table)
642
+ end
643
+
644
+ # @override
645
+ def foreign_keys(table_name)
646
+ @connection.foreign_keys(table_name)
647
+ end if ArJdbc::AR42
648
+
649
+ # Does our database (+ its JDBC driver) support foreign-keys?
650
+ # @since 1.3.18
651
+ # @override
652
+ def supports_foreign_keys?
653
+ @connection.supports_foreign_keys?
654
+ end if ArJdbc::AR42
655
+
656
+ # @deprecated Rather use {#update_lob_value} instead.
657
+ def write_large_object(*args)
658
+ @connection.write_large_object(*args)
659
+ end
660
+
661
+ # @param record the record e.g. `User.find(1)`
662
+ # @param column the model's column e.g. `User.columns_hash['photo']`
663
+ # @param value the lob value - string or (IO or Java) stream
664
+ def update_lob_value(record, column, value)
665
+ @connection.update_lob_value(record, column, value)
666
+ end
667
+
668
+ if ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR == 0
669
+
670
+ #attr_reader :visitor unless method_defined?(:visitor) # not in 3.0
671
+
672
+ # @private
673
+ def to_sql(arel, binds = nil)
674
+ # NOTE: can not handle `visitor.accept(arel.ast)` right
675
+ arel.respond_to?(:to_sql) ? arel.send(:to_sql) : arel
676
+ end
677
+
678
+ elsif ActiveRecord::VERSION::MAJOR < 3 # AR-2.3 'fake' #to_sql method
679
+
680
+ # @private
681
+ def to_sql(sql, binds = nil)
682
+ sql
683
+ end
684
+
685
+ end
686
+
687
+ protected
688
+
689
+ # @override so that we do not have to care having 2 arguments on 3.0
690
+ def log(sql, name = nil, binds = [])
691
+ unless binds.blank?
692
+ binds = binds.map do |column, value|
693
+ column ? [column.name, value] : [nil, value]
694
+ end
695
+ sql = "#{sql} #{binds.inspect}"
696
+ end
697
+ super(sql, name || 'SQL') # `log(sql, name)` on AR <= 3.0
698
+ end if ::ActiveRecord::VERSION::MAJOR < 3 ||
699
+ ( ::ActiveRecord::VERSION::MAJOR == 3 && ::ActiveRecord::VERSION::MINOR < 1 )
700
+
701
+ if ::ActiveRecord::VERSION::MAJOR > 3
702
+ # @private
703
+ WrappingStatementInvalid = ::ActiveRecord::StatementInvalid
704
+ elsif ::ActiveRecord::VERSION::MAJOR > 2
705
+ # @private AR 3.x : WrappedDatabaseException < StatementInvalid
706
+ WrappingStatementInvalid = ::ActiveRecord::WrappedDatabaseException
707
+ else # 2.3
708
+ # does not have a translate_exception but does this in log :
709
+ # raise ActiveRecord::StatementInvalid, message
710
+ #
711
+ # NOTE: still suitable to patch due JDBCError assuming super(msg, cause)
712
+ ::ActiveRecord::StatementInvalid.class_eval do
713
+ # attr_reader :original_exception
714
+ def initialize(message, original_exception = nil)
715
+ super(message)
716
+ @original_exception = original_exception
717
+ end
718
+ end
719
+ # @private
720
+ WrappingStatementInvalid = ::ActiveRecord::StatementInvalid
721
+ end
722
+
723
+ def translate_exception(e, message)
724
+ return e if e.is_a?(JDBCError)
725
+ # we shall not translate native "Java" exceptions as they might
726
+ # swallow an ArJdbc / driver bug into a AR::StatementInvalid ...
727
+ return e if e.is_a?(NativeException) # JRuby 1.6
728
+ return e if e.is_a?(Java::JavaLang::Throwable)
729
+
730
+ case e
731
+ when SystemExit, SignalException, NoMemoryError then e
732
+ else WrappingStatementInvalid.new(message, e) # super
733
+ end
734
+ end
735
+
736
+ # Take an id from the result of an INSERT query.
737
+ # @return [Integer, NilClass]
738
+ def last_inserted_id(result)
739
+ if result.is_a?(Hash) || result.is_a?(ActiveRecord::Result)
740
+ result.first.first[1] # .first = { "id"=>1 } .first = [ "id", 1 ]
741
+ else
742
+ result
743
+ end
744
+ end
745
+
746
+ # @private
747
+ def last_inserted_id(result)
748
+ if result.is_a?(Hash)
749
+ result.first.first[1] # .first = { "id"=>1 } .first = [ "id", 1 ]
750
+ else
751
+ result
752
+ end
753
+ end unless defined? ActiveRecord::Result
754
+
755
+ # NOTE: make sure if adapter overrides #table_definition that it will
756
+ # work on AR 3.x as well as 4.0
757
+ if ActiveRecord::VERSION::MAJOR > 3
758
+
759
+ # aliasing #create_table_definition as #table_definition :
760
+ alias table_definition create_table_definition
761
+
762
+ # `TableDefinition.new native_database_types, name, temporary, options`
763
+ # and ActiveRecord 4.1 supports optional `as` argument (which defaults
764
+ # to nil) to provide the SQL to use to generate the table:
765
+ # `TableDefinition.new native_database_types, name, temporary, options, as`
766
+ # @private
767
+ def create_table_definition(*args)
768
+ table_definition(*args)
769
+ end
770
+
771
+ # @note AR-4x arguments expected: `(name, temporary, options)`
772
+ # @private documented bellow
773
+ def new_table_definition(table_definition, *args)
774
+ table_definition.new native_database_types, *args
775
+ end
776
+ private :new_table_definition
777
+
778
+ # @private
779
+ def new_index_definition(table, name, unique, columns, lengths,
780
+ orders = nil, where = nil, type = nil, using = nil)
781
+ IndexDefinition.new(table, name, unique, columns, lengths, orders, where, type, using)
782
+ end
783
+ private :new_index_definition
784
+
785
+ #
786
+
787
+ # Provides backwards-compatibility on ActiveRecord 4.1 for DB adapters
788
+ # that override this and than call super expecting to work.
789
+ # @note This method is available in 4.0 but won't be in 4.1
790
+ # @private
791
+ def add_column_options!(sql, options)
792
+ sql << " DEFAULT #{quote(options[:default], options[:column])}" if options_include_default?(options)
793
+ # must explicitly check for :null to allow change_column to work on migrations
794
+ sql << " NOT NULL" if options[:null] == false
795
+ sql << " AUTO_INCREMENT" if options[:auto_increment] == true
796
+ end
797
+ public :add_column_options!
798
+
799
+ else # AR < 4.0
800
+
801
+ # Helper to easily override #table_definition (on AR 3.x/4.0) as :
802
+ # ```
803
+ # def table_definition(*args)
804
+ # new_table_definition(TableDefinition, *args)
805
+ # end
806
+ # ```
807
+ def new_table_definition(table_definition, *args)
808
+ table_definition.new(self) # args ignored only used for 4.0
809
+ end
810
+ private :new_table_definition
811
+
812
+ # @private (:table, :name, :unique, :columns, :lengths, :orders)
813
+ def new_index_definition(table, name, unique, columns, lengths,
814
+ orders = nil, where = nil, type = nil, using = nil)
815
+ IndexDefinition.new(table, name, unique, columns, lengths, orders)
816
+ end
817
+ # @private (:table, :name, :unique, :columns, :lengths)
818
+ def new_index_definition(table, name, unique, columns, lengths,
819
+ orders = nil, where = nil, type = nil, using = nil)
820
+ IndexDefinition.new(table, name, unique, columns, lengths)
821
+ end if ActiveRecord::VERSION::STRING < '3.2'
822
+ private :new_index_definition
823
+
824
+ end
825
+
826
+ # @return whether `:prepared_statements` are to be used
827
+ def prepared_statements?
828
+ return @prepared_statements unless (@prepared_statements ||= nil).nil?
829
+ @prepared_statements = self.class.prepared_statements?(config)
830
+ end
831
+
832
+ # Allows changing the prepared statements setting for this connection.
833
+ # @see #prepared_statements?
834
+ #def prepared_statements=(statements)
835
+ # @prepared_statements = statements
836
+ #end
837
+
838
+ def self.prepared_statements?(config)
839
+ config.key?(:prepared_statements) ?
840
+ type_cast_config_to_boolean(config.fetch(:prepared_statements)) :
841
+ false # off by default - NOTE: on AR 4.x it's on by default !?
842
+ end
843
+
844
+ if @@suble_binds = Java::JavaLang::System.getProperty('arjdbc.adapter.suble_binds')
845
+ @@suble_binds = Java::JavaLang::Boolean.parseBoolean(@@suble_binds)
846
+ else
847
+ @@suble_binds = ActiveRecord::VERSION::MAJOR < 4 # due compatibility
848
+ end
849
+ def self.suble_binds?; @@suble_binds; end
850
+ def self.suble_binds=(flag); @@suble_binds = flag; end
851
+
852
+ private
853
+
854
+ # @note Since AR 4.0 we (finally) do not "sub" SQL's '?' parameters !
855
+ # @deprecated This should go away (hopefully), now here due 1.2.x.
856
+ def suble_binds(sql, binds)
857
+ return sql if ! @@suble_binds || binds.nil? || binds.empty?
858
+ binds = binds.dup; warn = nil
859
+ result = sql.gsub('?') { warn = true; quote(*binds.shift.reverse) }
860
+ ActiveSupport::Deprecation.warn(
861
+ "string binds substitution is deprecated - please refactor your sql", caller[1..-1]
862
+ ) if warn
863
+ result
864
+ end
865
+
866
+ # @private Supporting "string-subling" on AR 4.0 would require {#to_sql}
867
+ # to consume binds parameters otherwise it happens twice e.g. for a record
868
+ # insert it is called during {#insert} as well as on {#exec_insert} ...
869
+ # but that than leads to other issues with libraries that save the binds
870
+ # array and run a query again since it's the very same instance on 4.0 !
871
+ def suble_binds(sql, binds)
872
+ sql
873
+ end if ActiveRecord::VERSION::MAJOR > 3
874
+
875
+ # @deprecated No longer used, will be removed.
876
+ # @see #suble_binds
877
+ def substitute_binds(sql, binds)
878
+ return sql if binds.nil? || binds.empty?; binds = binds.dup
879
+ extract_sql(sql).gsub('?') { quote(*binds.shift.reverse) }
880
+ end
881
+
882
+ # @deprecated No longer used, kept for 1.2 API compatibility.
883
+ def extract_sql(arel)
884
+ arel.respond_to?(:to_sql) ? arel.send(:to_sql) : arel
885
+ end
886
+
887
+ if ActiveRecord::VERSION::MAJOR > 2
888
+ # Helper useful during {#quote} since AREL might pass in it's literals
889
+ # to be quoted, fixed since AREL 4.0.0.beta1 : http://git.io/7gyTig
890
+ def sql_literal?(value); ::Arel::Nodes::SqlLiteral === value; end
891
+ else
892
+ # @private
893
+ def sql_literal?(value); false; end
894
+ end
895
+
896
+ # Helper to get local/UTC time (based on `ActiveRecord::Base.default_timezone`).
897
+ def get_time(value)
898
+ get = ::ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
899
+ value.respond_to?(get) ? value.send(get) : value
900
+ end
901
+
902
+ protected
903
+
904
+ # @return whether the given SQL string is a 'SELECT' like query (returning a results)
905
+ def self.select?(sql)
906
+ JdbcConnection::select?(sql)
907
+ end
908
+
909
+ # @return whether the given SQL string is an 'INSERT' query
910
+ def self.insert?(sql)
911
+ JdbcConnection::insert?(sql)
912
+ end
913
+
914
+ # @return whether the given SQL string is an 'UPDATE' (or 'DELETE') like query
915
+ def self.update?(sql)
916
+ ! select?(sql) && ! insert?(sql)
917
+ end
918
+
919
+ unless defined? AbstractAdapter.type_cast_config_to_integer
920
+
921
+ # @private
922
+ def self.type_cast_config_to_integer(config)
923
+ config =~ /\A\d+\z/ ? config.to_i : config
924
+ end
925
+
926
+ end
927
+
928
+ # @private
929
+ def self.type_cast_config_to_boolean(config)
930
+ config == 'false' ? false : (config == 'true' ? true : config)
931
+ end
932
+
933
+ public
934
+
935
+ # @note Used by Java API to convert dates from (custom) SELECTs (might get refactored).
936
+ # @private
937
+ def _string_to_date(value); jdbc_column_class.string_to_date(value) end
938
+
939
+ # @note Used by Java API to convert times from (custom) SELECTs (might get refactored).
940
+ # @private
941
+ def _string_to_time(value); jdbc_column_class.string_to_dummy_time(value) end
942
+
943
+ # @note Used by Java API to convert times from (custom) SELECTs (might get refactored).
944
+ # @private
945
+ def _string_to_timestamp(value); jdbc_column_class.string_to_time(value) end
946
+
947
+ if ActiveRecord::VERSION::STRING > '4.2'
948
+
949
+ # @private
950
+ @@_date = nil
951
+
952
+ # @private
953
+ def _string_to_date(value)
954
+ if jdbc_column_class.respond_to?(:string_to_date)
955
+ jdbc_column_class.string_to_date(value)
956
+ else
957
+ (@@_date ||= ActiveRecord::Type::Date.new).send(:cast_value, value)
958
+ end
959
+ end
960
+
961
+ # @private
962
+ @@_time = nil
963
+
964
+ # @private
965
+ def _string_to_time(value)
966
+ if jdbc_column_class.respond_to?(:string_to_dummy_time)
967
+ jdbc_column_class.string_to_dummy_time(value)
968
+ else
969
+ (@@_time ||= ActiveRecord::Type::Time.new).send(:cast_value, value)
970
+ end
971
+ end
972
+
973
+ # @private
974
+ @@_date_time = nil
975
+
976
+ # @private
977
+ def _string_to_timestamp(value)
978
+ if jdbc_column_class.respond_to?(:string_to_time)
979
+ jdbc_column_class.string_to_time(value)
980
+ else
981
+ (@@_date_time ||= ActiveRecord::Type::DateTime.new).send(:cast_value, value)
982
+ end
983
+ end
984
+
985
+ end
986
+
987
+ if ActiveRecord::VERSION::MAJOR < 4 # emulating Rails 3.x compatibility
988
+ JdbcConnection.raw_date_time = true if JdbcConnection.raw_date_time?.nil?
989
+ JdbcConnection.raw_boolean = true if JdbcConnection.raw_boolean?.nil?
990
+ elsif ArJdbc::AR42 # AR::Type should do the conversion - for better accuracy
991
+ JdbcConnection.raw_date_time = true if JdbcConnection.raw_date_time?.nil?
992
+ JdbcConnection.raw_boolean = true if JdbcConnection.raw_boolean?.nil?
993
+ end
994
+
995
+ end
996
+ end
997
+ end