activerecord-jdbc-adapter-ficoh 1.3.21-java

Sign up to get free protection for your applications and to get access to all the features.
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