activerecord-jdbc-alt-adapter 50.3.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (198) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +35 -0
  3. data/.travis.yml +100 -0
  4. data/.yardopts +4 -0
  5. data/CONTRIBUTING.md +50 -0
  6. data/Gemfile +92 -0
  7. data/History.md +1191 -0
  8. data/LICENSE.txt +26 -0
  9. data/README.md +240 -0
  10. data/RUNNING_TESTS.md +127 -0
  11. data/Rakefile +336 -0
  12. data/Rakefile.jdbc +20 -0
  13. data/activerecord-jdbc-adapter.gemspec +55 -0
  14. data/activerecord-jdbc-alt-adapter.gemspec +56 -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/postgresql_adapter.rb +1 -0
  29. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -0
  30. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +1 -0
  31. data/lib/activerecord-jdbc-adapter.rb +1 -0
  32. data/lib/arel/visitors/compat.rb +60 -0
  33. data/lib/arel/visitors/db2.rb +137 -0
  34. data/lib/arel/visitors/derby.rb +112 -0
  35. data/lib/arel/visitors/firebird.rb +79 -0
  36. data/lib/arel/visitors/h2.rb +25 -0
  37. data/lib/arel/visitors/hsqldb.rb +32 -0
  38. data/lib/arel/visitors/postgresql_jdbc.rb +6 -0
  39. data/lib/arel/visitors/sql_server.rb +225 -0
  40. data/lib/arel/visitors/sql_server/ng42.rb +294 -0
  41. data/lib/arel/visitors/sqlserver.rb +214 -0
  42. data/lib/arjdbc.rb +19 -0
  43. data/lib/arjdbc/abstract/connection_management.rb +35 -0
  44. data/lib/arjdbc/abstract/core.rb +74 -0
  45. data/lib/arjdbc/abstract/database_statements.rb +64 -0
  46. data/lib/arjdbc/abstract/statement_cache.rb +58 -0
  47. data/lib/arjdbc/abstract/transaction_support.rb +86 -0
  48. data/lib/arjdbc/db2.rb +4 -0
  49. data/lib/arjdbc/db2/adapter.rb +789 -0
  50. data/lib/arjdbc/db2/as400.rb +130 -0
  51. data/lib/arjdbc/db2/column.rb +167 -0
  52. data/lib/arjdbc/db2/connection_methods.rb +44 -0
  53. data/lib/arjdbc/derby.rb +3 -0
  54. data/lib/arjdbc/derby/active_record_patch.rb +13 -0
  55. data/lib/arjdbc/derby/adapter.rb +540 -0
  56. data/lib/arjdbc/derby/connection_methods.rb +20 -0
  57. data/lib/arjdbc/derby/schema_creation.rb +15 -0
  58. data/lib/arjdbc/discover.rb +104 -0
  59. data/lib/arjdbc/firebird.rb +4 -0
  60. data/lib/arjdbc/firebird/adapter.rb +434 -0
  61. data/lib/arjdbc/firebird/connection_methods.rb +23 -0
  62. data/lib/arjdbc/h2.rb +3 -0
  63. data/lib/arjdbc/h2/adapter.rb +303 -0
  64. data/lib/arjdbc/h2/connection_methods.rb +27 -0
  65. data/lib/arjdbc/hsqldb.rb +3 -0
  66. data/lib/arjdbc/hsqldb/adapter.rb +297 -0
  67. data/lib/arjdbc/hsqldb/connection_methods.rb +28 -0
  68. data/lib/arjdbc/hsqldb/explain_support.rb +35 -0
  69. data/lib/arjdbc/hsqldb/schema_creation.rb +11 -0
  70. data/lib/arjdbc/informix.rb +5 -0
  71. data/lib/arjdbc/informix/adapter.rb +162 -0
  72. data/lib/arjdbc/informix/connection_methods.rb +9 -0
  73. data/lib/arjdbc/jdbc.rb +59 -0
  74. data/lib/arjdbc/jdbc/adapter.rb +475 -0
  75. data/lib/arjdbc/jdbc/adapter_require.rb +46 -0
  76. data/lib/arjdbc/jdbc/base_ext.rb +15 -0
  77. data/lib/arjdbc/jdbc/callbacks.rb +53 -0
  78. data/lib/arjdbc/jdbc/column.rb +97 -0
  79. data/lib/arjdbc/jdbc/connection.rb +14 -0
  80. data/lib/arjdbc/jdbc/connection_methods.rb +37 -0
  81. data/lib/arjdbc/jdbc/error.rb +65 -0
  82. data/lib/arjdbc/jdbc/extension.rb +59 -0
  83. data/lib/arjdbc/jdbc/java.rb +13 -0
  84. data/lib/arjdbc/jdbc/railtie.rb +2 -0
  85. data/lib/arjdbc/jdbc/rake_tasks.rb +3 -0
  86. data/lib/arjdbc/jdbc/serialized_attributes_helper.rb +3 -0
  87. data/lib/arjdbc/jdbc/type_cast.rb +166 -0
  88. data/lib/arjdbc/jdbc/type_converter.rb +142 -0
  89. data/lib/arjdbc/mssql.rb +7 -0
  90. data/lib/arjdbc/mssql/adapter.rb +384 -0
  91. data/lib/arjdbc/mssql/column.rb +29 -0
  92. data/lib/arjdbc/mssql/connection_methods.rb +79 -0
  93. data/lib/arjdbc/mssql/database_statements.rb +134 -0
  94. data/lib/arjdbc/mssql/errors.rb +6 -0
  95. data/lib/arjdbc/mssql/explain_support.rb +129 -0
  96. data/lib/arjdbc/mssql/extensions.rb +36 -0
  97. data/lib/arjdbc/mssql/limit_helpers.rb +231 -0
  98. data/lib/arjdbc/mssql/lock_methods.rb +77 -0
  99. data/lib/arjdbc/mssql/old_adapter.rb +804 -0
  100. data/lib/arjdbc/mssql/old_column.rb +200 -0
  101. data/lib/arjdbc/mssql/quoting.rb +101 -0
  102. data/lib/arjdbc/mssql/schema_creation.rb +31 -0
  103. data/lib/arjdbc/mssql/schema_definitions.rb +74 -0
  104. data/lib/arjdbc/mssql/schema_statements.rb +329 -0
  105. data/lib/arjdbc/mssql/transaction.rb +69 -0
  106. data/lib/arjdbc/mssql/types.rb +52 -0
  107. data/lib/arjdbc/mssql/types/binary_types.rb +33 -0
  108. data/lib/arjdbc/mssql/types/date_and_time_types.rb +134 -0
  109. data/lib/arjdbc/mssql/types/deprecated_types.rb +40 -0
  110. data/lib/arjdbc/mssql/types/numeric_types.rb +71 -0
  111. data/lib/arjdbc/mssql/types/string_types.rb +56 -0
  112. data/lib/arjdbc/mssql/utils.rb +66 -0
  113. data/lib/arjdbc/mysql.rb +3 -0
  114. data/lib/arjdbc/mysql/adapter.rb +140 -0
  115. data/lib/arjdbc/mysql/connection_methods.rb +166 -0
  116. data/lib/arjdbc/oracle/adapter.rb +863 -0
  117. data/lib/arjdbc/postgresql.rb +3 -0
  118. data/lib/arjdbc/postgresql/adapter.rb +687 -0
  119. data/lib/arjdbc/postgresql/base/array_decoder.rb +26 -0
  120. data/lib/arjdbc/postgresql/base/array_encoder.rb +25 -0
  121. data/lib/arjdbc/postgresql/base/array_parser.rb +95 -0
  122. data/lib/arjdbc/postgresql/base/pgconn.rb +11 -0
  123. data/lib/arjdbc/postgresql/column.rb +51 -0
  124. data/lib/arjdbc/postgresql/connection_methods.rb +67 -0
  125. data/lib/arjdbc/postgresql/name.rb +24 -0
  126. data/lib/arjdbc/postgresql/oid_types.rb +266 -0
  127. data/lib/arjdbc/railtie.rb +11 -0
  128. data/lib/arjdbc/sqlite3.rb +3 -0
  129. data/lib/arjdbc/sqlite3/adapter.rb +678 -0
  130. data/lib/arjdbc/sqlite3/connection_methods.rb +59 -0
  131. data/lib/arjdbc/sybase.rb +2 -0
  132. data/lib/arjdbc/sybase/adapter.rb +47 -0
  133. data/lib/arjdbc/tasks.rb +13 -0
  134. data/lib/arjdbc/tasks/database_tasks.rb +31 -0
  135. data/lib/arjdbc/tasks/databases.rake +48 -0
  136. data/lib/arjdbc/tasks/db2_database_tasks.rb +104 -0
  137. data/lib/arjdbc/tasks/derby_database_tasks.rb +95 -0
  138. data/lib/arjdbc/tasks/h2_database_tasks.rb +31 -0
  139. data/lib/arjdbc/tasks/hsqldb_database_tasks.rb +70 -0
  140. data/lib/arjdbc/tasks/jdbc_database_tasks.rb +169 -0
  141. data/lib/arjdbc/tasks/mssql_database_tasks.rb +46 -0
  142. data/lib/arjdbc/util/quoted_cache.rb +60 -0
  143. data/lib/arjdbc/util/serialized_attributes.rb +98 -0
  144. data/lib/arjdbc/util/table_copier.rb +110 -0
  145. data/lib/arjdbc/version.rb +3 -0
  146. data/lib/generators/jdbc/USAGE +9 -0
  147. data/lib/generators/jdbc/jdbc_generator.rb +17 -0
  148. data/lib/jdbc_adapter.rb +2 -0
  149. data/lib/jdbc_adapter/rake_tasks.rb +4 -0
  150. data/lib/jdbc_adapter/version.rb +4 -0
  151. data/pom.xml +114 -0
  152. data/rails_generators/jdbc_generator.rb +15 -0
  153. data/rails_generators/templates/config/initializers/jdbc.rb +10 -0
  154. data/rails_generators/templates/lib/tasks/jdbc.rake +11 -0
  155. data/rakelib/01-tomcat.rake +51 -0
  156. data/rakelib/02-test.rake +132 -0
  157. data/rakelib/bundler_ext.rb +11 -0
  158. data/rakelib/db.rake +75 -0
  159. data/rakelib/rails.rake +223 -0
  160. data/src/java/arjdbc/ArJdbcModule.java +276 -0
  161. data/src/java/arjdbc/db2/DB2Module.java +76 -0
  162. data/src/java/arjdbc/db2/DB2RubyJdbcConnection.java +126 -0
  163. data/src/java/arjdbc/derby/DerbyModule.java +178 -0
  164. data/src/java/arjdbc/derby/DerbyRubyJdbcConnection.java +152 -0
  165. data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +174 -0
  166. data/src/java/arjdbc/h2/H2Module.java +50 -0
  167. data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +85 -0
  168. data/src/java/arjdbc/hsqldb/HSQLDBModule.java +73 -0
  169. data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +75 -0
  170. data/src/java/arjdbc/jdbc/AdapterJavaService.java +43 -0
  171. data/src/java/arjdbc/jdbc/Callable.java +44 -0
  172. data/src/java/arjdbc/jdbc/ConnectionFactory.java +45 -0
  173. data/src/java/arjdbc/jdbc/DataSourceConnectionFactory.java +156 -0
  174. data/src/java/arjdbc/jdbc/DriverConnectionFactory.java +63 -0
  175. data/src/java/arjdbc/jdbc/DriverWrapper.java +119 -0
  176. data/src/java/arjdbc/jdbc/JdbcResult.java +130 -0
  177. data/src/java/arjdbc/jdbc/RubyConnectionFactory.java +61 -0
  178. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +3979 -0
  179. data/src/java/arjdbc/mssql/MSSQLModule.java +90 -0
  180. data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +508 -0
  181. data/src/java/arjdbc/mysql/MySQLModule.java +152 -0
  182. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +294 -0
  183. data/src/java/arjdbc/oracle/OracleModule.java +80 -0
  184. data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +455 -0
  185. data/src/java/arjdbc/postgresql/ByteaUtils.java +157 -0
  186. data/src/java/arjdbc/postgresql/PgDateTimeUtils.java +52 -0
  187. data/src/java/arjdbc/postgresql/PostgreSQLModule.java +77 -0
  188. data/src/java/arjdbc/postgresql/PostgreSQLResult.java +192 -0
  189. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +948 -0
  190. data/src/java/arjdbc/sqlite3/SQLite3Module.java +73 -0
  191. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +525 -0
  192. data/src/java/arjdbc/util/CallResultSet.java +826 -0
  193. data/src/java/arjdbc/util/DateTimeUtils.java +699 -0
  194. data/src/java/arjdbc/util/ObjectSupport.java +65 -0
  195. data/src/java/arjdbc/util/QuotingUtils.java +137 -0
  196. data/src/java/arjdbc/util/StringCache.java +63 -0
  197. data/src/java/arjdbc/util/StringHelper.java +145 -0
  198. metadata +269 -0
@@ -0,0 +1,28 @@
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
+ begin
9
+ require 'jdbc/hsqldb'
10
+ ::Jdbc::HSQLDB.load_driver(:require) if defined?(::Jdbc::HSQLDB.load_driver)
11
+ rescue LoadError # assuming driver.jar is on the class-path
12
+ end
13
+
14
+ config[:url] ||= begin
15
+ db = config[:database]
16
+ if db[0, 4] == 'mem:' || db[0, 5] == 'file:' || db[0, 5] == 'hsql:'
17
+ "jdbc:hsqldb:#{db}"
18
+ else
19
+ "jdbc:hsqldb:file:#{db}"
20
+ end
21
+ end
22
+ config[:driver] ||= defined?(::Jdbc::HSQLDB.driver_name) ? ::Jdbc::HSQLDB.driver_name : 'org.hsqldb.jdbcDriver'
23
+ config[:connection_alive_sql] ||= 'CALL PI()' # does not like 'SELECT 1'
24
+
25
+ embedded_driver(config)
26
+ end
27
+ alias_method :jdbchsqldb_connection, :hsqldb_connection
28
+ 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,162 @@
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 = ::ArJdbc::SerializedAttributesHelper.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
40
+ ::ActiveRecord::ConnectionAdapters::InformixJdbcConnection
41
+ end
42
+
43
+ # @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_column_class
44
+ def jdbc_column_class
45
+ ::ActiveRecord::ConnectionAdapters::InformixColumn
46
+ end
47
+
48
+ module ColumnMethods
49
+
50
+ private
51
+ # TODO: Test all Informix column types.
52
+ def simplified_type(field_type)
53
+ if field_type =~ /serial/i
54
+ :primary_key
55
+ else
56
+ super
57
+ end
58
+ end
59
+
60
+ end
61
+
62
+ def modify_types(types)
63
+ super(types)
64
+ types[:primary_key] = "SERIAL PRIMARY KEY"
65
+ types[:string] = { :name => "VARCHAR", :limit => 255 }
66
+ types[:integer] = { :name => "INTEGER" }
67
+ types[:float] = { :name => "FLOAT" }
68
+ types[:decimal] = { :name => "DECIMAL" }
69
+ types[:datetime] = { :name => "DATETIME YEAR TO FRACTION(5)" }
70
+ types[:timestamp] = { :name => "DATETIME YEAR TO FRACTION(5)" }
71
+ types[:time] = { :name => "DATETIME HOUR TO FRACTION(5)" }
72
+ types[:date] = { :name => "DATE" }
73
+ types[:binary] = { :name => "BYTE" }
74
+ types[:boolean] = { :name => "BOOLEAN" }
75
+ types
76
+ end
77
+
78
+ def prefetch_primary_key?(table_name = nil)
79
+ true
80
+ end
81
+
82
+ def supports_migrations?
83
+ true
84
+ end
85
+
86
+ def default_sequence_name(table, column)
87
+ "#{table}_seq"
88
+ end
89
+
90
+ def add_limit_offset!(sql, options)
91
+ if options[:limit]
92
+ limit = "FIRST #{options[:limit]}" # SKIP available only in IDS >= 10 :
93
+ offset = (db_major_version >= 10 && options[:offset] ? "SKIP #{options[:offset]}" : "")
94
+ sql.sub!(/^\s*?select /i, "SELECT #{offset} #{limit} ")
95
+ end
96
+ sql
97
+ end
98
+
99
+ def next_sequence_value(sequence_name)
100
+ select_one("SELECT #{sequence_name}.nextval id FROM systables WHERE tabid=1")['id']
101
+ end
102
+
103
+ # TODO: Add some smart quoting for newlines in string and text fields.
104
+ def quote_string(string)
105
+ string.gsub(/\'/, "''")
106
+ end
107
+
108
+ def quote(value, column = nil)
109
+ column_type = column && column.type
110
+ if column_type == :binary || column_type == :text
111
+ # LOBs are updated separately by an after_save trigger.
112
+ "NULL"
113
+ elsif column_type == :date
114
+ "'#{value.mon}/#{value.day}/#{value.year}'"
115
+ else
116
+ super
117
+ end
118
+ end
119
+
120
+ def create_table(name, options = {})
121
+ super(name, options)
122
+ execute("CREATE SEQUENCE #{name}_seq")
123
+ end
124
+
125
+ def rename_table(name, new_name)
126
+ execute("RENAME TABLE #{name} TO #{new_name}")
127
+ execute("RENAME SEQUENCE #{name}_seq TO #{new_name}_seq")
128
+ end
129
+
130
+ def drop_table(name)
131
+ super(name)
132
+ execute("DROP SEQUENCE #{name}_seq")
133
+ end
134
+
135
+ def remove_index(table_name, options = {})
136
+ @connection.execute_update("DROP INDEX #{index_name(table_name, options)}")
137
+ end
138
+
139
+ def select(sql, *rest)
140
+ # Informix does not like "= NULL", "!= NULL", or "<> NULL".
141
+ super(sql.gsub(/(!=|<>)\s*null/i, "IS NOT NULL").gsub(/=\s*null/i, "IS NULL"), *rest)
142
+ end
143
+
144
+ private
145
+
146
+ def db_major_version
147
+ @@db_major_version ||=
148
+ select_one("SELECT dbinfo('version', 'major') version FROM systables WHERE tabid = 1")['version'].to_i
149
+ end
150
+
151
+ end # module Informix
152
+ end # module ::ArJdbc
153
+
154
+ module ActiveRecord::ConnectionAdapters
155
+ class InformixColumn < JdbcColumn
156
+ include ::ArJdbc::Informix::ColumnMethods
157
+ end
158
+
159
+ class InformixAdapter < JdbcAdapter
160
+ include ::ArJdbc::Informix
161
+ end
162
+ 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,59 @@
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(message) || true if warn?(message, once)
31
+ end
32
+
33
+ def deprecate(message, once = nil) # adds a "DEPRECATION WARNING: " prefix
34
+ ::ActiveSupport::Deprecation.warn(message, caller_locations) || true if warn?(message, once)
35
+ end
36
+
37
+ private
38
+
39
+ @@warns = nil
40
+ @@warns = false if ENV_JAVA['arjdbc.warn'].eql? 'false'
41
+
42
+ def warn?(message, once)
43
+ return nil if @@warns.equal?(false) || ! message
44
+ warns = @@warns ||= ( require 'set'; Set.new )
45
+ return false if warns.include?(message)
46
+ warns << message.dup if once
47
+ true
48
+ end
49
+
50
+ end
51
+
52
+ require 'arjdbc/jdbc/adapter'
53
+
54
+ if ENV_JAVA['arjdbc.extensions.discover'].eql? 'true'
55
+ self.discover_extensions
56
+ else
57
+ require 'arjdbc/discover'
58
+ end
59
+ end
@@ -0,0 +1,475 @@
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/callbacks'
12
+ require 'arjdbc/jdbc/extension'
13
+ require 'arjdbc/jdbc/type_converter'
14
+ require 'arjdbc/abstract/core'
15
+ require 'arjdbc/abstract/connection_management'
16
+ require 'arjdbc/abstract/database_statements'
17
+ require 'arjdbc/abstract/transaction_support'
18
+
19
+ module ActiveRecord
20
+ module ConnectionAdapters
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
+ include Jdbc::ConnectionPoolCallbacks
40
+
41
+ include ArJdbc::Abstract::Core
42
+ include ArJdbc::Abstract::ConnectionManagement
43
+ include ArJdbc::Abstract::DatabaseStatements
44
+ include ArJdbc::Abstract::TransactionSupport
45
+
46
+ attr_reader :prepared_statements
47
+
48
+ # Returns the (JDBC) connection class to be used for this adapter.
49
+ # This is used by (database specific) spec modules to override the class
50
+ # used assuming some of the available methods have been re-defined.
51
+ # @see ActiveRecord::ConnectionAdapters::JdbcConnection
52
+ def jdbc_connection_class(spec)
53
+ connection_class = spec.jdbc_connection_class if spec && spec.respond_to?(:jdbc_connection_class)
54
+ connection_class ? connection_class : ::ActiveRecord::ConnectionAdapters::JdbcConnection
55
+ end
56
+
57
+ # Returns the (JDBC) `ActiveRecord` column class for this adapter.
58
+ # This is used by (database specific) spec modules to override the class.
59
+ # @see ActiveRecord::ConnectionAdapters::JdbcColumn
60
+ def jdbc_column_class
61
+ ::ActiveRecord::ConnectionAdapters::JdbcColumn
62
+ end
63
+
64
+ # Locate the specialized (database specific) adapter specification module
65
+ # if one exists based on provided configuration data. This module will than
66
+ # extend an instance of the adapter (unless an `:adapter_class` provided).
67
+ #
68
+ # This method is called during {#initialize} unless an explicit
69
+ # `config[:adapter_spec]` is set.
70
+ # @param config the configuration to check for `:adapter_spec`
71
+ # @return [Module] the database specific module
72
+ def adapter_spec(config)
73
+ dialect = (config[:dialect] || config[:driver]).to_s
74
+ ::ArJdbc.modules.each do |constant| # e.g. ArJdbc::MySQL
75
+ if constant.respond_to?(:adapter_matcher)
76
+ spec = constant.adapter_matcher(dialect, config)
77
+ return spec if spec
78
+ end
79
+ end
80
+
81
+ unless config.key?(:dialect)
82
+ begin # does nothing unless config[:jndi] || config[:data_source]
83
+ dialect = ::ArJdbc.with_meta_data_from_data_source_if_any(config) do
84
+ |meta_data| config[:dialect] = meta_data.getDatabaseProductName
85
+ end
86
+ return adapter_spec(config) if dialect # re-try matching with :dialect
87
+ rescue => e
88
+ ::ArJdbc.warn("failed to set :dialect from database meda-data: #{e.inspect}")
89
+ else
90
+ return adapter_spec(config) # re-try matching a spec with set config[:dialect]
91
+ end
92
+ end
93
+
94
+ nil
95
+ end
96
+
97
+ ADAPTER_NAME = 'JDBC'.freeze
98
+
99
+ # @return [String] the 'JDBC' adapter name.
100
+ def adapter_name
101
+ ADAPTER_NAME
102
+ end
103
+
104
+ # @override
105
+ # Will return true even when native adapter classes passed in
106
+ # e.g. `jdbc_adapter.is_a? ConnectionAdapter::PostgresqlAdapter`
107
+ #
108
+ # This is only necessary (for built-in adapters) when
109
+ # `config[:adapter_class]` is forced to `nil` and the `:adapter_spec`
110
+ # module is used to extend the `JdbcAdapter`, otherwise we replace the
111
+ # class constants for built-in adapters (MySQL, PostgreSQL and SQLite3).
112
+ def is_a?(klass)
113
+ # This is to fake out current_adapter? conditional logic in AR tests
114
+ if klass.is_a?(Class) && klass.name =~ /#{adapter_name}Adapter$/i
115
+ true
116
+ else
117
+ super
118
+ end
119
+ end
120
+
121
+ # @deprecated re-implemented - no longer used
122
+ # @return [Hash] the AREL visitor to use
123
+ # If there's a `self.arel2_visitors(config)` method on the adapter
124
+ # spec than it is preferred and will be used instead of this one.
125
+ def self.arel2_visitors(config)
126
+ { 'jdbc' => ::Arel::Visitors::ToSql }
127
+ end
128
+
129
+ # @deprecated re-implemented - no longer used
130
+ # @see #arel2_visitors
131
+ def self.configure_arel2_visitors(config)
132
+ visitors = ::Arel::Visitors::VISITORS
133
+ klass = config[:adapter_spec]
134
+ klass = self unless klass.respond_to?(:arel2_visitors)
135
+ visitor = nil
136
+ klass.arel2_visitors(config).each do |name, arel|
137
+ visitors[name] = ( visitor = arel )
138
+ end
139
+ if visitor && config[:adapter] =~ /^(jdbc|jndi)$/
140
+ visitors[ config[:adapter] ] = visitor
141
+ end
142
+ visitor
143
+ end
144
+
145
+ # DB specific types are detected but adapter specs (or extenders) are
146
+ # expected to hand tune these types for concrete databases.
147
+ # @return [Hash] the native database types
148
+ # @override
149
+ def native_database_types
150
+ @native_database_types ||= begin
151
+ types = @connection.native_database_types
152
+ modify_types(types)
153
+ types
154
+ end
155
+ end
156
+
157
+ # @override introduced in AR 4.2
158
+ def valid_type?(type)
159
+ ! native_database_types[type].nil?
160
+ end
161
+
162
+ # Allows for modification of the detected native types.
163
+ # @param types the resolved native database types
164
+ # @see #native_database_types
165
+ def modify_types(types)
166
+ types
167
+ end
168
+
169
+ # Abstract adapter default implementation does nothing silently.
170
+ # @override
171
+ def structure_dump
172
+ raise NotImplementedError, "structure_dump not supported"
173
+ end
174
+
175
+ # JDBC adapters support migration.
176
+ # @return [true]
177
+ # @override
178
+ def supports_migrations?
179
+ true
180
+ end
181
+
182
+ # Returns the underlying database name.
183
+ # @override
184
+ def database_name
185
+ @connection.database_name
186
+ end
187
+
188
+ # @private
189
+ def native_sql_to_type(type)
190
+ if /^(.*?)\(([0-9]+)\)/ =~ type
191
+ tname, limit = $1, $2.to_i
192
+ ntypes = native_database_types
193
+ if ntypes[:primary_key] == type
194
+ return :primary_key, nil
195
+ else
196
+ ntypes.each do |name, val|
197
+ if name == :primary_key
198
+ next
199
+ end
200
+ if val[:name].downcase == tname.downcase &&
201
+ ( val[:limit].nil? || val[:limit].to_i == limit )
202
+ return name, limit
203
+ end
204
+ end
205
+ end
206
+ elsif /^(.*?)/ =~ type
207
+ tname = $1
208
+ ntypes = native_database_types
209
+ if ntypes[:primary_key] == type
210
+ return :primary_key, nil
211
+ else
212
+ ntypes.each do |name, val|
213
+ if val[:name].downcase == tname.downcase && val[:limit].nil?
214
+ return name, nil
215
+ end
216
+ end
217
+ end
218
+ else
219
+ return :string, 255
220
+ end
221
+ return nil, nil
222
+ end
223
+
224
+ def columns(table_name, name = nil)
225
+ @connection.columns(table_name.to_s)
226
+ end
227
+
228
+ # @override
229
+ def supports_views?
230
+ @connection.supports_views?
231
+ end
232
+
233
+ # Similar to {#exec_query} except it returns "raw" results in an array
234
+ # where each rows is a hash with keys as columns (just like Rails used to
235
+ # do up until 3.0) instead of wrapping them in a {#ActiveRecord::Result}.
236
+ # @param sql the query string (or AREL object)
237
+ # @param name logging marker for the executed SQL statement log entry
238
+ # @param binds the bind parameters
239
+ # @yield [v1, v2] depending on the row values returned from the query
240
+ # In case a block is given it will yield each row from the result set
241
+ # instead of returning mapped query results in an array.
242
+ # @return [Array] unless a block is given
243
+ def exec_query_raw(sql, name = 'SQL', binds = [], &block)
244
+ sql = to_sql(sql, binds) if sql.respond_to?(:to_sql)
245
+
246
+ if prepared_statements?
247
+ log(sql, name, binds) { @connection.execute_query_raw(sql, binds, &block) }
248
+ else
249
+ log(sql, name) { @connection.execute_query_raw(sql, &block) }
250
+ end
251
+ end
252
+
253
+ # @private
254
+ # @override
255
+ def select_rows(sql, name = nil, binds = [])
256
+ exec_query_raw(sql, name, binds).map!(&:values)
257
+ end
258
+
259
+ # Executes the SQL statement in the context of this connection.
260
+ # The return value from this method depends on the SQL type (whether
261
+ # it's a SELECT, INSERT etc.). For INSERTs a generated id might get
262
+ # returned while for UPDATE statements the affected row count.
263
+ # Please note that this method returns "raw" results (in an array) for
264
+ # statements that return a result set, while {#exec_query} is expected to
265
+ # return a `ActiveRecord::Result` (since AR 3.1).
266
+ # @note This method does not use prepared statements.
267
+ # @note The method does not emulate various "native" `execute` results on MRI.
268
+ # @see #exec_query
269
+ # @see #exec_insert
270
+ # @see #exec_update
271
+ def execute(sql, name = nil, binds = nil)
272
+ sql = to_sql(sql, binds) if binds
273
+ if name == :skip_logging
274
+ _execute(sql, name)
275
+ else
276
+ log(sql, name) { _execute(sql, name) }
277
+ end
278
+ end
279
+
280
+ # We need to do it this way, to allow Rails stupid tests to always work
281
+ # even if we define a new `execute` method. Instead of mixing in a new
282
+ # `execute`, an `_execute` should be mixed in.
283
+ # @deprecated it was only introduced due tests
284
+ # @private
285
+ def _execute(sql, name = nil)
286
+ @connection.execute(sql)
287
+ end
288
+ private :_execute
289
+
290
+ # Kind of `execute(sql) rescue nil` but logging failures at debug level only.
291
+ def execute_quietly(sql, name = 'SQL')
292
+ log(sql, name) do
293
+ begin
294
+ _execute(sql)
295
+ rescue => e
296
+ logger.debug("#{e.class}: #{e.message}: #{sql}")
297
+ end
298
+ end
299
+ end
300
+
301
+ # @override
302
+ def tables(name = nil)
303
+ @connection.tables
304
+ end
305
+
306
+ # @override
307
+ def table_exists?(name)
308
+ return false unless name
309
+ @connection.table_exists?(name) # schema_name = nil
310
+ end
311
+
312
+ # @override
313
+ def data_sources
314
+ tables
315
+ end
316
+
317
+ # @override
318
+ def data_source_exists?(name)
319
+ table_exists?(name)
320
+ end
321
+
322
+ # @override
323
+ def indexes(table_name, name = nil, schema_name = nil)
324
+ @connection.indexes(table_name, name, schema_name)
325
+ end
326
+
327
+ # @override
328
+ def pk_and_sequence_for(table)
329
+ ( key = primary_key(table) ) ? [ key, nil ] : nil
330
+ end
331
+
332
+ # @override
333
+ def primary_keys(table)
334
+ @connection.primary_keys(table)
335
+ end
336
+
337
+ # @override
338
+ def foreign_keys(table_name)
339
+ @connection.foreign_keys(table_name)
340
+ end
341
+
342
+ # Does our database (+ its JDBC driver) support foreign-keys?
343
+ # @since 1.3.18
344
+ # @override
345
+ def supports_foreign_keys?
346
+ @connection.supports_foreign_keys?
347
+ end
348
+
349
+ # @deprecated Rather use {#update_lob_value} instead.
350
+ def write_large_object(*args)
351
+ @connection.write_large_object(*args)
352
+ end
353
+
354
+ # @param record the record e.g. `User.find(1)`
355
+ # @param column the model's column e.g. `User.columns_hash['photo']`
356
+ # @param value the lob value - string or (IO or Java) stream
357
+ def update_lob_value(record, column, value)
358
+ @connection.update_lob_value(record, column, value)
359
+ end
360
+
361
+ protected
362
+
363
+ # Take an id from the result of an INSERT query.
364
+ # @return [Integer, NilClass]
365
+ def last_inserted_id(result)
366
+ if result.is_a?(Hash) || result.is_a?(ActiveRecord::Result)
367
+ result.first.first[1] # .first = { "id"=>1 } .first = [ "id", 1 ]
368
+ else
369
+ result
370
+ end
371
+ end
372
+
373
+ # aliasing #create_table_definition as #table_definition :
374
+ alias table_definition create_table_definition
375
+
376
+ # `TableDefinition.new native_database_types, name, temporary, options`
377
+ # and ActiveRecord 4.1 supports optional `as` argument (which defaults
378
+ # to nil) to provide the SQL to use to generate the table:
379
+ # `TableDefinition.new native_database_types, name, temporary, options, as`
380
+ # @private
381
+ def create_table_definition(*args)
382
+ table_definition(*args)
383
+ end
384
+
385
+ # @note AR-4x arguments expected: `(name, temporary, options)`
386
+ # @private documented bellow
387
+ def new_table_definition(table_definition, *args)
388
+ table_definition.new(*args)
389
+ end
390
+ private :new_table_definition
391
+
392
+ # @private
393
+ def new_index_definition(table, name, unique, columns, lengths,
394
+ orders = nil, where = nil, type = nil, using = nil)
395
+ IndexDefinition.new(table, name, unique, columns, lengths, orders, where, type, using)
396
+ end
397
+ private :new_index_definition
398
+
399
+ #
400
+
401
+ # Provides backwards-compatibility on ActiveRecord 4.1 for DB adapters
402
+ # that override this and than call super expecting to work.
403
+ # @note This method is available in 4.0 but won't be in 4.1
404
+ # @private
405
+ def add_column_options!(sql, options)
406
+ sql << " DEFAULT #{quote(options[:default], options[:column])}" if options_include_default?(options)
407
+ # must explicitly check for :null to allow change_column to work on migrations
408
+ sql << " NOT NULL" if options[:null] == false
409
+ sql << " AUTO_INCREMENT" if options[:auto_increment] == true
410
+ end
411
+ public :add_column_options!
412
+
413
+ # @return whether `:prepared_statements` are to be used
414
+ def prepared_statements?
415
+ return @prepared_statements unless (@prepared_statements ||= nil).nil?
416
+ @prepared_statements = self.class.prepared_statements?(config)
417
+ end
418
+
419
+ # Allows changing the prepared statements setting for this connection.
420
+ # @see #prepared_statements?
421
+ #def prepared_statements=(statements)
422
+ # @prepared_statements = statements
423
+ #end
424
+
425
+ def self.prepared_statements?(config)
426
+ config.key?(:prepared_statements) ?
427
+ type_cast_config_to_boolean(config.fetch(:prepared_statements)) :
428
+ false # off by default - NOTE: on AR 4.x it's on by default !?
429
+ end
430
+
431
+ private
432
+
433
+ # Helper useful during {#quote} since AREL might pass in it's literals
434
+ # to be quoted, fixed since AREL 4.0.0.beta1 : http://git.io/7gyTig
435
+ def sql_literal?(value); ::Arel::Nodes::SqlLiteral === value; end
436
+
437
+ # Helper to get local/UTC time (based on `ActiveRecord::Base.default_timezone`).
438
+ def get_time(value)
439
+ get = ::ActiveRecord::Base.default_timezone == :utc ? :getutc : :getlocal
440
+ value.respond_to?(get) ? value.send(get) : value
441
+ end
442
+
443
+ # @return whether the given SQL string is a 'SELECT' like
444
+ # query (returning a result set)
445
+ def self.select?(sql)
446
+ JdbcConnection::select?(sql)
447
+ end
448
+
449
+ # @return whether the given SQL string is an 'INSERT' query
450
+ def self.insert?(sql)
451
+ JdbcConnection::insert?(sql)
452
+ end
453
+
454
+ # @return whether the given SQL string is an 'UPDATE' (or 'DELETE') query
455
+ def self.update?(sql)
456
+ ! select?(sql) && ! insert?(sql)
457
+ end
458
+
459
+ unless defined? AbstractAdapter.type_cast_config_to_integer
460
+
461
+ # @private
462
+ def self.type_cast_config_to_integer(config)
463
+ config =~ /\A\d+\z/ ? config.to_i : config
464
+ end
465
+
466
+ end
467
+
468
+ # @private
469
+ def self.type_cast_config_to_boolean(config)
470
+ config == 'false' ? false : (config == 'true' ? true : config)
471
+ end
472
+
473
+ end
474
+ end
475
+ end