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,86 @@
1
+ module ArJdbc
2
+ module Abstract
3
+
4
+ # Provides the basic interface needed to support transactions for JDBC based adapters
5
+ module TransactionSupport
6
+
7
+ ########################## Support Checks #################################
8
+
9
+ # Does our database (+ its JDBC driver) support save-points?
10
+ # @since 1.3.0
11
+ # @override
12
+ def supports_savepoints?
13
+ @connection.supports_savepoints?
14
+ end
15
+
16
+ # Does this adapter support setting the isolation level for a transaction?
17
+ # Unlike 'plain' `ActiveRecord` we allow checking for concrete transaction
18
+ # isolation level support by the database.
19
+ # @param level optional to check if we support a specific isolation level
20
+ # @since 1.3.0
21
+ # @extension added optional level parameter
22
+ def supports_transaction_isolation?(level = nil)
23
+ return false unless level
24
+ @connection.supports_transaction_isolation?(level)
25
+ end
26
+
27
+ ########################## Transaction Interface ##########################
28
+
29
+ # Starts a database transaction.
30
+ # @override
31
+ def begin_db_transaction
32
+ log('BEGIN TRANSACTION'.freeze, nil) { @connection.begin }
33
+ end
34
+
35
+ # Starts a database transaction.
36
+ # @param isolation the transaction isolation to use
37
+ def begin_isolated_db_transaction(isolation)
38
+ log("BEGIN ISOLATED TRANSACTION - #{isolation}", nil) { @connection.begin(isolation) }
39
+ end
40
+
41
+ # Commits the current database transaction.
42
+ # @override
43
+ def commit_db_transaction
44
+ log('COMMIT TRANSACTION'.freeze, nil) { @connection.commit }
45
+ end
46
+
47
+ # Rolls back the current database transaction.
48
+ # Called from 'rollback_db_transaction' in the AbstractAdapter
49
+ # @override
50
+ def exec_rollback_db_transaction
51
+ log('ROLLBACK TRANSACTION'.freeze, nil) { @connection.rollback }
52
+ end
53
+
54
+ ########################## Savepoint Interface ############################
55
+
56
+ # Creates a (transactional) save-point one can rollback to.
57
+ # Unlike 'plain' `ActiveRecord` it is allowed to pass a save-point name.
58
+ # @param name the save-point name
59
+ # @return save-point name (even if nil passed will be generated)
60
+ # @since 1.3.0
61
+ # @extension added optional name parameter
62
+ def create_savepoint(name = current_savepoint_name)
63
+ log("SAVEPOINT #{name}", 'Savepoint') { @connection.create_savepoint(name) }
64
+ end
65
+
66
+ # Transaction rollback to a given (previously created) save-point.
67
+ # If no save-point name given rollback to the last created one.
68
+ # Called from 'rollback_to_savepoint' in AbstractAdapter
69
+ # @param name the save-point name
70
+ # @extension added optional name parameter
71
+ def exec_rollback_to_savepoint(name = current_savepoint_name)
72
+ log("ROLLBACK TO SAVEPOINT #{name}", 'Savepoint') { @connection.rollback_savepoint(name) }
73
+ end
74
+
75
+ # Release a previously created save-point.
76
+ # @note Save-points are auto-released with the transaction they're created
77
+ # in (on transaction commit or roll-back).
78
+ # @param name the save-point name
79
+ # @extension added optional name parameter
80
+ def release_savepoint(name = current_savepoint_name)
81
+ log("RELEASE SAVEPOINT #{name}", 'Savepoint') { @connection.release_savepoint(name) }
82
+ end
83
+
84
+ end
85
+ end
86
+ end
data/lib/arjdbc/db2.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'arjdbc'
2
+ require 'arjdbc/db2/adapter'
3
+ require 'arjdbc/db2/connection_methods'
4
+ ArJdbc.warn_unsupported_adapter 'db2', [4, 2] # warns on AR >= 4.2
@@ -0,0 +1,789 @@
1
+ # NOTE: file contains code adapted from **ruby-ibmdb** adapter, license follows
2
+ =begin
3
+ Copyright (c) 2006 - 2015 IBM Corporation
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ =end
24
+
25
+ ArJdbc.load_java_part :DB2
26
+
27
+ require 'arjdbc/db2/column'
28
+
29
+ module ArJdbc
30
+ # @note This adapter doesn't support explain `config.active_record.auto_explain_threshold_in_seconds` should be commented (Rails < 4.0)
31
+ module DB2
32
+
33
+ # @private
34
+ def self.extended(adapter); initialize!; end
35
+
36
+ # @private
37
+ @@_initialized = nil
38
+
39
+ # @private
40
+ def self.initialize!
41
+ return if @@_initialized; @@_initialized = true
42
+
43
+ require 'arjdbc/util/serialized_attributes'
44
+ Util::SerializedAttributes.setup /blob|clob/i, 'after_save_with_db2_lob'
45
+ end
46
+
47
+ # @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_connection_class
48
+ def self.jdbc_connection_class
49
+ ::ActiveRecord::ConnectionAdapters::DB2JdbcConnection
50
+ end
51
+
52
+ # @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_column_class
53
+ def jdbc_column_class
54
+ ::ActiveRecord::ConnectionAdapters::DB2Column
55
+ end
56
+
57
+ # @private
58
+ @@emulate_booleans = true
59
+
60
+ # Boolean emulation can be disabled using :
61
+ #
62
+ # ArJdbc::DB2.emulate_booleans = false
63
+ #
64
+ def self.emulate_booleans?; @@emulate_booleans; end
65
+ # @deprecated Use {#emulate_booleans?} instead.
66
+ def self.emulate_booleans; @@emulate_booleans; end
67
+ # @see #emulate_booleans?
68
+ def self.emulate_booleans=(emulate); @@emulate_booleans = emulate; end
69
+
70
+ # @private
71
+ @@update_lob_values = true
72
+
73
+ # Updating records with LOB values (binary/text columns) in a separate
74
+ # statement can be disabled using :
75
+ #
76
+ # ArJdbc::DB2.update_lob_values = false
77
+ #
78
+ # @note This only applies when prepared statements are not used.
79
+ def self.update_lob_values?; @@update_lob_values; end
80
+ # @see #update_lob_values?
81
+ def self.update_lob_values=(update); @@update_lob_values = update; end
82
+
83
+ # @see #update_lob_values?
84
+ # @see ArJdbc::Util::SerializedAttributes#update_lob_columns
85
+ def update_lob_value?(value, column = nil)
86
+ DB2.update_lob_values? && ! prepared_statements? # && value
87
+ end
88
+
89
+ # @see #quote
90
+ # @private
91
+ BLOB_VALUE_MARKER = "BLOB('')"
92
+ # @see #quote
93
+ # @private
94
+ CLOB_VALUE_MARKER = "''"
95
+
96
+ def configure_connection
97
+ schema = self.schema
98
+ set_schema(schema) if schema && schema != config[:username]
99
+ end
100
+
101
+ ADAPTER_NAME = 'DB2'.freeze
102
+
103
+ def adapter_name
104
+ ADAPTER_NAME
105
+ end
106
+
107
+ NATIVE_DATABASE_TYPES = {
108
+ :string => { :name => "varchar", :limit => 255 },
109
+ :integer => { :name => "integer" },
110
+ :bigint => { :name => 'bigint' },
111
+ :float => { :name => "real" }, # :limit => 24
112
+ :double => { :name => "double" }, # :limit => 53
113
+ :text => { :name => "clob" },
114
+ :binary => { :name => "blob" },
115
+ :xml => { :name => "xml" },
116
+ :decimal => { :name => "decimal" }, # :limit => 31
117
+ :char => { :name => "char" }, # :limit => 254
118
+ :date => { :name => "date" },
119
+ :datetime => { :name => "timestamp" },
120
+ :timestamp => { :name => "timestamp" },
121
+ :time => { :name => "time" },
122
+ :boolean => { :name => "smallint" }, # no native boolean type
123
+ #:rowid => { :name => "rowid" }, # rowid is a supported datatype on z/OS and i/5
124
+ #:serial => { :name => "serial" }, # supported datatype on Informix Dynamic Server
125
+ #:graphic => { :name => "graphic", :limit => 1 }, # :limit => 127
126
+ }
127
+
128
+ # @override
129
+ def initialize_type_map(m)
130
+ register_class_with_limit m, %r(boolean)i, ActiveRecord::Type::Boolean
131
+ register_class_with_limit m, %r(char)i, ActiveRecord::Type::String
132
+ register_class_with_limit m, %r(binary)i, ActiveRecord::Type::Binary
133
+ register_class_with_limit m, %r(text)i, ActiveRecord::Type::Text
134
+ register_class_with_limit m, %r(date)i, ActiveRecord::Type::Date
135
+ register_class_with_limit m, %r(time)i, ActiveRecord::Type::Time
136
+ register_class_with_limit m, %r(datetime)i, ActiveRecord::Type::DateTime
137
+ register_class_with_limit m, %r(float)i, ActiveRecord::Type::Float
138
+ register_class_with_limit m, %r(int)i, ActiveRecord::Type::Integer
139
+
140
+ m.alias_type %r(blob)i, 'binary'
141
+ m.alias_type %r(clob)i, 'text'
142
+ m.alias_type %r(timestamp)i, 'datetime'
143
+ m.alias_type %r(numeric)i, 'decimal'
144
+ m.alias_type %r(number)i, 'decimal'
145
+ m.alias_type %r(double)i, 'float'
146
+ m.alias_type %r(real)i, 'float'
147
+
148
+ m.register_type(%r(decimal)i) do |sql_type|
149
+ scale = extract_scale(sql_type)
150
+ precision = extract_precision(sql_type)
151
+ limit = extract_limit(sql_type)
152
+ if scale == 0
153
+ ActiveRecord::Type::BigInteger.new(:precision => precision, :limit => limit)
154
+ else
155
+ ActiveRecord::Type::Decimal.new(:precision => precision, :scale => scale)
156
+ end
157
+ end
158
+
159
+ m.alias_type %r(for bit data)i, 'binary'
160
+ m.alias_type %r(smallint)i, 'boolean'
161
+ m.alias_type %r(serial)i, 'int'
162
+ m.alias_type %r(decfloat)i, 'decimal'
163
+ #m.alias_type %r(real)i, 'decimal'
164
+ m.alias_type %r(graphic)i, 'binary'
165
+ m.alias_type %r(rowid)i, 'int'
166
+
167
+ m.register_type(%r(smallint)i) do
168
+ if DB2.emulate_booleans?
169
+ ActiveRecord::Type::Boolean.new
170
+ else
171
+ ActiveRecord::Type::Integer.new(:limit => 1)
172
+ end
173
+ end
174
+
175
+ m.register_type %r(xml)i, XmlType.new
176
+ end if AR42
177
+
178
+ # @private
179
+ class XmlType < ActiveRecord::Type::String
180
+ def type; :xml end
181
+
182
+ def type_cast_for_database(value)
183
+ return unless value
184
+ Data.new(super)
185
+ end
186
+
187
+ class Data
188
+ def initialize(value)
189
+ @value = value
190
+ end
191
+ def to_s; @value end
192
+ end
193
+ end if AR42
194
+
195
+ # @override
196
+ def reset_column_information
197
+ initialize_type_map(type_map)
198
+ end if AR42
199
+
200
+ # @override
201
+ def native_database_types
202
+ # NOTE: currently merging with what JDBC gives us since there's a lot
203
+ # of DB2-like stuff we could be connecting e.g. "classic", Z/OS etc.
204
+ # types = super
205
+ types = super.merge(NATIVE_DATABASE_TYPES)
206
+ types
207
+ end
208
+
209
+ # @private
210
+ class TableDefinition < ::ActiveRecord::ConnectionAdapters::TableDefinition
211
+
212
+ def xml(*args)
213
+ options = args.extract_options!
214
+ column(args[0], 'xml', options)
215
+ end
216
+
217
+ # IBM DB adapter (MRI) compatibility :
218
+
219
+ # @private
220
+ # @deprecated
221
+ def double(*args)
222
+ options = args.extract_options!
223
+ column(args[0], 'double', options)
224
+ end
225
+
226
+ # @private
227
+ def decfloat(*args)
228
+ options = args.extract_options!
229
+ column(args[0], 'decfloat', options)
230
+ end
231
+
232
+ def graphic(*args)
233
+ options = args.extract_options!
234
+ column(args[0], 'graphic', options)
235
+ end
236
+
237
+ # @private
238
+ # @deprecated
239
+ def vargraphic(*args)
240
+ options = args.extract_options!
241
+ column(args[0], 'vargraphic', options)
242
+ end
243
+
244
+ # @private
245
+ # @deprecated
246
+ def bigint(*args)
247
+ options = args.extract_options!
248
+ column(args[0], 'bigint', options)
249
+ end
250
+
251
+ def char(*args)
252
+ options = args.extract_options!
253
+ column(args[0], 'char', options)
254
+ end
255
+ # alias_method :character, :char
256
+
257
+ end
258
+
259
+ def table_definition(*args)
260
+ new_table_definition(TableDefinition, *args)
261
+ end
262
+
263
+ def prefetch_primary_key?(table_name = nil)
264
+ # TRUE if the table has no identity column
265
+ names = table_name.upcase.split(".")
266
+ sql = "SELECT 1 FROM SYSCAT.COLUMNS WHERE IDENTITY = 'Y' "
267
+ sql << "AND TABSCHEMA = '#{names.first}' " if names.size == 2
268
+ sql << "AND TABNAME = '#{names.last}'"
269
+ select_one(sql).nil?
270
+ end
271
+
272
+ def next_sequence_value(sequence_name)
273
+ select_value("SELECT NEXT VALUE FOR #{sequence_name} FROM sysibm.sysdummy1")
274
+ end
275
+
276
+ def create_table(name, options = {}, &block)
277
+ if zos?
278
+ zos_create_table(name, options, &block)
279
+ else
280
+ super
281
+ end
282
+ end
283
+
284
+ def zos_create_table(name, options = {})
285
+ table_definition = new_table_definition TableDefinition, name, options[:temporary], options[:options], options[:as]
286
+
287
+ unless options[:id] == false
288
+ table_definition.primary_key(options[:primary_key] || primary_key(name))
289
+ end
290
+
291
+ yield table_definition if block_given?
292
+
293
+ # Clobs in DB2 Host have to be created after the Table with an auxiliary Table.
294
+ clob_columns = []
295
+ table_definition.columns.delete_if do |column|
296
+ if column.type && column.type.to_sym == :text
297
+ clob_columns << column; true
298
+ end
299
+ end
300
+
301
+ drop_table(name, options) if options[:force] && table_exists?(name)
302
+
303
+ create_sql = "CREATE#{' TEMPORARY' if options[:temporary]} TABLE "
304
+ create_sql << "#{quote_table_name(name)} ("
305
+ create_sql << table_definition.to_sql
306
+ create_sql << ") #{options[:options]}"
307
+ if @config[:database] && @config[:tablespace]
308
+ create_sql << " IN #{@config[:database]}.#{@config[:tablespace]}"
309
+ end
310
+
311
+ execute create_sql
312
+
313
+ # Table definition is complete only when a unique index is created on the primary_key column for DB2 V8 on zOS
314
+ # create index on id column if options[:id] is nil or id ==true
315
+ # else check if options[:primary_key]is not nil then create an unique index on that column
316
+ # TODO someone on Z/OS should test this out - also not needed for V9 ?
317
+ #primary_column = options[:id] == true ? 'id' : options[:primary_key]
318
+ #add_index(name, (primary_column || 'id').to_s, :unique => true)
319
+
320
+ clob_columns.each do |clob_column|
321
+ column_name = clob_column.name.to_s
322
+ execute "ALTER TABLE #{name} ADD COLUMN #{column_name} clob"
323
+ clob_table_name = "#{name}_#{column_name}_CD_"
324
+ if @config[:database] && @config[:lob_tablespaces]
325
+ in_lob_table_space = " IN #{@config[:database]}.#{@config[:lob_tablespaces][name.split(".")[1]]}"
326
+ end
327
+ execute "CREATE AUXILIARY TABLE #{clob_table_name} #{in_lob_table_space} STORES #{name} COLUMN #{column_name}"
328
+ execute "CREATE UNIQUE INDEX #{clob_table_name} ON #{clob_table_name};"
329
+ end
330
+ end
331
+ private :zos_create_table
332
+
333
+ def pk_and_sequence_for(table)
334
+ # In JDBC/DB2 side, only upcase names of table and column are handled.
335
+ keys = super(table.upcase)
336
+ if keys && keys[0]
337
+ # In ActiveRecord side, only downcase names of table and column are handled.
338
+ keys[0] = keys[0].downcase
339
+ end
340
+ keys
341
+ end
342
+
343
+ # Properly quotes the various data types.
344
+ # @param value contains the data
345
+ # @param column (optional) contains info on the field
346
+ # @override
347
+ def quote(value, column = nil)
348
+ return value.quoted_id if value.respond_to?(:quoted_id)
349
+ return value if sql_literal?(value)
350
+
351
+ if column
352
+ if column.respond_to?(:primary) && column.primary && column.klass != String
353
+ return value.to_i.to_s
354
+ end
355
+ if value && (column.type.to_sym == :decimal || column.type.to_sym == :integer)
356
+ return value.to_s
357
+ end
358
+ end
359
+
360
+ column_type = column && column.type.to_sym
361
+
362
+ case value
363
+ when nil then 'NULL'
364
+ when Numeric # IBM_DB doesn't accept quotes on numeric types
365
+ # if the column type is text or string, return the quote value
366
+ if column_type == :text || column_type == :string
367
+ "'#{value}'"
368
+ else
369
+ value.to_s
370
+ end
371
+ when String, ActiveSupport::Multibyte::Chars
372
+ if column_type == :binary && column.sql_type !~ /for bit data/i
373
+ if update_lob_value?(value, column)
374
+ value.nil? ? 'NULL' : BLOB_VALUE_MARKER # '@@@IBMBINARY@@@'"
375
+ else
376
+ "BLOB('#{quote_string(value)}')"
377
+ end
378
+ elsif column && column.sql_type =~ /clob/ # :text
379
+ if update_lob_value?(value, column)
380
+ value.nil? ? 'NULL' : CLOB_VALUE_MARKER # "'@@@IBMTEXT@@@'"
381
+ else
382
+ "'#{quote_string(value)}'"
383
+ end
384
+ elsif column_type == :xml
385
+ value.nil? ? 'NULL' : "'#{quote_string(value)}'" # "'<ibm>@@@IBMXML@@@</ibm>'"
386
+ else
387
+ "'#{quote_string(value)}'"
388
+ end
389
+ when Symbol then "'#{quote_string(value.to_s)}'"
390
+ when Time
391
+ # AS400 doesn't support date in time column
392
+ if column_type == :time
393
+ quote_time(value)
394
+ else
395
+ super
396
+ end
397
+ else super
398
+ end
399
+ end
400
+
401
+ # @override
402
+ def quoted_date(value)
403
+ if value.acts_like?(:time) && value.respond_to?(:usec)
404
+ usec = sprintf("%06d", value.usec)
405
+ value = ::ActiveRecord::Base.default_timezone == :utc ? value.getutc : value.getlocal
406
+ "#{value.strftime("%Y-%m-%d %H:%M:%S")}.#{usec}"
407
+ else
408
+ super
409
+ end
410
+ end if ::ActiveRecord::VERSION::MAJOR >= 3
411
+
412
+ def quote_time(value)
413
+ value = ::ActiveRecord::Base.default_timezone == :utc ? value.getutc : value.getlocal
414
+ # AS400 doesn't support date in time column
415
+ "'#{value.strftime("%H:%M:%S")}'"
416
+ end
417
+
418
+ def quote_column_name(column_name)
419
+ column_name.to_s
420
+ end
421
+
422
+ def modify_types(types)
423
+ super(types)
424
+ types[:primary_key] = 'int not null generated by default as identity (start with 1) primary key'
425
+ types[:string][:limit] = 255
426
+ types[:integer][:limit] = nil
427
+ types[:boolean] = {:name => "decimal(1)"}
428
+ types
429
+ end
430
+
431
+ def type_to_sql(type, limit = nil, precision = nil, scale = nil)
432
+ limit = nil if type.to_sym == :integer
433
+ super(type, limit, precision, scale)
434
+ end
435
+
436
+ # @private
437
+ VALUES_DEFAULT = 'VALUES ( DEFAULT )' # NOTE: Arel::Visitors::DB2 uses this
438
+
439
+ # @override
440
+ def empty_insert_statement_value
441
+ VALUES_DEFAULT # won't work as DB2 needs to know the column count
442
+ end
443
+
444
+ def add_column(table_name, column_name, type, options = {})
445
+ # The keyword COLUMN allows to use reserved names for columns (ex: date)
446
+ add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ADD COLUMN #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
447
+ add_column_options!(add_column_sql, options)
448
+ execute(add_column_sql)
449
+ end
450
+
451
+ def add_column_options!(sql, options)
452
+ # handle case of defaults for CLOB columns,
453
+ # which might get incorrect if we write LOBs in the after_save callback
454
+ if options_include_default?(options)
455
+ column = options[:column]
456
+ if column && column.type == :text
457
+ sql << " DEFAULT #{quote(options.delete(:default))}"
458
+ end
459
+ if column && column.type == :binary
460
+ # quoting required for the default value of a column :
461
+ value = options.delete(:default)
462
+ # DB2 z/OS only allows NULL or "" (empty) string as DEFAULT value
463
+ # for a BLOB column. non-empty string and non-NULL, return error!
464
+ if value.nil?
465
+ sql_value = "NULL"
466
+ else
467
+ sql_value = zos? ? "#{value}" : "BLOB('#{quote_string(value)}'"
468
+ end
469
+ sql << " DEFAULT #{sql_value}"
470
+ end
471
+ end
472
+ super
473
+ end
474
+
475
+ # @note Only used with (non-AREL) ActiveRecord **2.3**.
476
+ # @see Arel::Visitors::DB2
477
+ def add_limit_offset!(sql, options)
478
+ limit = options[:limit]
479
+ replace_limit_offset!(sql, limit, options[:offset]) if limit
480
+ end if ::ActiveRecord::VERSION::MAJOR < 3
481
+
482
+ # @private shared with {Arel::Visitors::DB2}
483
+ def replace_limit_offset!(sql, limit, offset, orders = nil)
484
+ limit = limit.to_i
485
+
486
+ if offset # && limit
487
+ over_order_by = nil # NOTE: orders matching got reverted as it was not complete and there were no case covering it ...
488
+
489
+ start_sql = "SELECT B.* FROM (SELECT A.*, row_number() OVER (#{over_order_by}) AS internal$rownum FROM (SELECT"
490
+ end_sql = ") A ) B WHERE B.internal$rownum > #{offset} AND B.internal$rownum <= #{limit + offset.to_i}"
491
+
492
+ if sql.is_a?(String)
493
+ sql.sub!(/SELECT/i, start_sql)
494
+ sql << end_sql
495
+ else # AR 4.2 sql.class ... Arel::Collectors::Bind
496
+ sql.parts[0] = start_sql # sql.sub! /SELECT/i
497
+ sql.parts[ sql.parts.length ] = end_sql
498
+ end
499
+ else
500
+ limit_sql = limit == 1 ? " FETCH FIRST ROW ONLY" : " FETCH FIRST #{limit} ROWS ONLY"
501
+ if sql.is_a?(String)
502
+ sql << limit_sql
503
+ else # AR 4.2 sql.class ... Arel::Collectors::Bind
504
+ sql.parts[ sql.parts.length ] = limit_sql
505
+ end
506
+ end
507
+ sql
508
+ end
509
+
510
+ # @deprecated seems not sued nor tested ?!
511
+ def runstats_for_table(tablename, priority = 10)
512
+ @connection.execute_update "call sysproc.admin_cmd('RUNSTATS ON TABLE #{tablename} WITH DISTRIBUTION AND DETAILED INDEXES ALL UTIL_IMPACT_PRIORITY #{priority}')"
513
+ end
514
+
515
+ if ::ActiveRecord::VERSION::MAJOR >= 4
516
+
517
+ def select(sql, name = nil, binds = [])
518
+ exec_query(to_sql(suble_null_test(sql), binds), name, binds)
519
+ end
520
+
521
+ else
522
+
523
+ def select(sql, name = nil, binds = [])
524
+ exec_query_raw(to_sql(suble_null_test(sql), binds), name, binds)
525
+ end
526
+
527
+ end
528
+
529
+ # @private
530
+ IS_NOT_NULL = /(!=|<>)\s*NULL/i
531
+ # @private
532
+ IS_NULL = /=\s*NULL/i
533
+
534
+ def suble_null_test(sql)
535
+ return sql unless sql.is_a?(String)
536
+ # DB2 does not like "= NULL", "!= NULL", or "<> NULL" :
537
+ sql = sql.dup
538
+ sql.gsub! IS_NOT_NULL, 'IS NOT NULL'
539
+ sql.gsub! IS_NULL, 'IS NULL'
540
+ sql
541
+ end
542
+ private :suble_null_test
543
+
544
+ def add_index(table_name, column_name, options = {})
545
+ if ! zos? || ( table_name.to_s == ActiveRecord::Migrator.schema_migrations_table_name.to_s )
546
+ column_name = column_name.to_s if column_name.is_a?(Symbol)
547
+ super
548
+ else
549
+ statement = 'CREATE'
550
+ statement << ' UNIQUE ' if options[:unique]
551
+ statement << " INDEX #{ActiveRecord::Base.table_name_prefix}#{options[:name]} "
552
+ statement << " ON #{table_name}(#{column_name})"
553
+
554
+ execute statement
555
+ end
556
+ end
557
+
558
+ # @override
559
+ def remove_index!(table_name, index_name)
560
+ execute "DROP INDEX #{quote_column_name(index_name)}"
561
+ end
562
+
563
+ # http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.admin.dbobj.doc/doc/t0020130.html
564
+ # ...not supported on IBM i, so we raise in this case
565
+ def rename_column(table_name, column_name, new_column_name) #:nodoc:
566
+ sql = "ALTER TABLE #{table_name} RENAME COLUMN #{column_name} TO #{new_column_name}"
567
+ execute_table_change(sql, table_name, 'Rename Column')
568
+ end
569
+
570
+ def change_column_null(table_name, column_name, null)
571
+ if null
572
+ sql = "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} DROP NOT NULL"
573
+ else
574
+ sql = "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET NOT NULL"
575
+ end
576
+ execute_table_change(sql, table_name, 'Change Column')
577
+ end
578
+
579
+ def change_column_default(table_name, column_name, default)
580
+ if default.nil?
581
+ sql = "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} DROP DEFAULT"
582
+ else
583
+ sql = "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET WITH DEFAULT #{quote(default)}"
584
+ end
585
+ execute_table_change(sql, table_name, 'Change Column')
586
+ end
587
+
588
+ def change_column(table_name, column_name, type, options = {})
589
+ data_type = type_to_sql(type, options[:limit], options[:precision], options[:scale])
590
+ sql = "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET DATA TYPE #{data_type}"
591
+ execute_table_change(sql, table_name, 'Change Column')
592
+
593
+ if options.include?(:default) and options.include?(:null)
594
+ # which to run first?
595
+ if options[:null] or options[:default].nil?
596
+ change_column_null(table_name, column_name, options[:null])
597
+ change_column_default(table_name, column_name, options[:default])
598
+ else
599
+ change_column_default(table_name, column_name, options[:default])
600
+ change_column_null(table_name, column_name, options[:null])
601
+ end
602
+ elsif options.include?(:default)
603
+ change_column_default(table_name, column_name, options[:default])
604
+ elsif options.include?(:null)
605
+ change_column_null(table_name, column_name, options[:null])
606
+ end
607
+ end
608
+
609
+ if ActiveRecord::VERSION::MAJOR >= 4
610
+
611
+ def remove_column(table_name, column_name, type = nil, options = {})
612
+ db2_remove_column(table_name, column_name)
613
+ end
614
+
615
+ else
616
+
617
+ def remove_column(table_name, *column_names)
618
+ # http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.admin.dbobj.doc/doc/t0020132.html
619
+ outcome = nil
620
+ column_names = column_names.flatten
621
+ for column_name in column_names
622
+ outcome = db2_remove_column(table_name, column_name)
623
+ end
624
+ column_names.size == 1 ? outcome : nil
625
+ end
626
+
627
+ end
628
+
629
+ def rename_table(name, new_name)
630
+ # http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.sql.ref.doc/doc/r0000980.html
631
+ execute_table_change("RENAME TABLE #{name} TO #{new_name}", new_name, 'Rename Table')
632
+ end
633
+
634
+ def tables
635
+ @connection.tables(nil, schema)
636
+ end
637
+
638
+ # only record precision and scale for types that can set them via CREATE TABLE:
639
+ # http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.sql.ref.doc/doc/r0000927.html
640
+
641
+ HAVE_LIMIT = %w(FLOAT DECFLOAT CHAR VARCHAR CLOB BLOB NCHAR NCLOB DBCLOB GRAPHIC VARGRAPHIC) # TIMESTAMP
642
+ HAVE_PRECISION = %w(DECIMAL NUMERIC)
643
+ HAVE_SCALE = %w(DECIMAL NUMERIC)
644
+
645
+ def columns(table_name, name = nil)
646
+ columns = @connection.columns_internal(table_name.to_s, nil, schema) # catalog == nil
647
+
648
+ if zos?
649
+ # Remove the mighty db2_generated_rowid_for_lobs from the list of columns
650
+ columns = columns.reject { |col| "db2_generated_rowid_for_lobs" == col.name }
651
+ end
652
+ # scrub out sizing info when CREATE TABLE doesn't support it
653
+ # but JDBC reports it (doh!)
654
+ for column in columns
655
+ base_sql_type = column.sql_type.sub(/\(.*/, "").upcase
656
+ column.limit = nil unless HAVE_LIMIT.include?(base_sql_type)
657
+ column.precision = nil unless HAVE_PRECISION.include?(base_sql_type)
658
+ #column.scale = nil unless HAVE_SCALE.include?(base_sql_type)
659
+ end
660
+
661
+ columns
662
+ end
663
+
664
+ def indexes(table_name, name = nil)
665
+ @connection.indexes(table_name, name, schema)
666
+ end
667
+
668
+ def recreate_database(name = nil, options = {})
669
+ drop_database(name)
670
+ end
671
+
672
+ def drop_database(name = nil)
673
+ tables.each { |table| drop_table("#{table}") }
674
+ end
675
+
676
+ def truncate(table_name, name = nil)
677
+ execute "TRUNCATE TABLE #{quote_table_name(table_name)} IMMEDIATE", name
678
+ end
679
+
680
+ # @override
681
+ def supports_views?; true end
682
+
683
+ def execute_table_change(sql, table_name, name = nil)
684
+ outcome = execute(sql, name)
685
+ reorg_table(table_name, name)
686
+ outcome
687
+ end
688
+ protected :execute_table_change
689
+
690
+ def reorg_table(table_name, name = nil)
691
+ exec_update "call sysproc.admin_cmd ('REORG TABLE #{table_name}')", name, []
692
+ end
693
+ private :reorg_table
694
+
695
+ # alias_method :execute_and_auto_confirm, :execute
696
+
697
+ # Returns the value of an identity column of the last *INSERT* statement
698
+ # made over this connection.
699
+ # @note Check the *IDENTITY_VAL_LOCAL* function for documentation.
700
+ # @return [Fixnum]
701
+ def last_insert_id
702
+ @connection.identity_val_local
703
+ end
704
+
705
+ # NOTE: only setup query analysis on AR <= 3.0 since on 3.1 {#exec_query},
706
+ # {#exec_insert} will be used for AR generated queries/inserts etc.
707
+ # Also there's prepared statement support and {#execute} is meant to stay
708
+ # as a way of running non-prepared SQL statements (returning raw results).
709
+ if ActiveRecord::VERSION::MAJOR < 3 ||
710
+ ( ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR < 1 )
711
+
712
+ def _execute(sql, name = nil)
713
+ if self.class.select?(sql)
714
+ @connection.execute_query_raw(sql)
715
+ elsif self.class.insert?(sql)
716
+ @connection.execute_insert(sql) || last_insert_id
717
+ else
718
+ @connection.execute_update(sql)
719
+ end
720
+ end
721
+ private :_execute
722
+
723
+ end
724
+
725
+ DRIVER_NAME = 'com.ibm.db2.jcc.DB2Driver'.freeze
726
+
727
+ # @private
728
+ def zos?
729
+ @zos = nil unless defined? @zos
730
+ return @zos unless @zos.nil?
731
+ @zos =
732
+ if url = config[:url]
733
+ !!( url =~ /^jdbc:db2j:net:/ && config[:driver] == DRIVER_NAME )
734
+ else
735
+ nil
736
+ end
737
+ end
738
+
739
+ # @private
740
+ # @deprecated no longer used
741
+ def as400?
742
+ false
743
+ end
744
+
745
+ def schema
746
+ db2_schema
747
+ end
748
+
749
+ def schema=(schema)
750
+ set_schema(@db2_schema = schema) if db2_schema != schema
751
+ end
752
+
753
+ private
754
+
755
+ def set_schema(schema)
756
+ execute("SET SCHEMA #{schema}")
757
+ end
758
+
759
+ def db2_schema
760
+ @db2_schema = false unless defined? @db2_schema
761
+ return @db2_schema if @db2_schema != false
762
+ schema = config[:schema]
763
+ @db2_schema =
764
+ if schema then schema
765
+ elsif config[:jndi] || config[:data_source]
766
+ nil # let JNDI worry about schema
767
+ else
768
+ # LUW implementation uses schema name of username by default
769
+ config[:username] || ENV['USER']
770
+ end
771
+ end
772
+
773
+ def db2_remove_column(table_name, column_name)
774
+ sql = "ALTER TABLE #{quote_table_name(table_name)} DROP COLUMN #{quote_column_name(column_name)}"
775
+ execute_table_change(sql, table_name, 'Remove Column')
776
+ end
777
+
778
+ end
779
+ end
780
+
781
+ module ActiveRecord::ConnectionAdapters
782
+
783
+ remove_const(:DB2Column) if const_defined?(:DB2Column)
784
+
785
+ class DB2Column < JdbcColumn
786
+ include ::ArJdbc::DB2::Column
787
+ end
788
+
789
+ end