activerecord-jdbc-alt-adapter 50.3.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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