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,130 @@
1
+ require 'arjdbc/db2/adapter'
2
+
3
+ module ArJdbc
4
+ module AS400
5
+ include DB2
6
+
7
+ # @private
8
+ def self.extended(adapter); DB2.extended(adapter); end
9
+
10
+ # @private
11
+ def self.initialize!; DB2.initialize!; end
12
+
13
+ # @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_connection_class
14
+ def self.jdbc_connection_class; DB2.jdbc_connection_class; end
15
+
16
+ def self.column_selector
17
+ [ /as400/i, lambda { |config, column| column.extend(Column) } ]
18
+ end
19
+
20
+ # Boolean emulation can be disabled using :
21
+ #
22
+ # ArJdbc::AS400.emulate_booleans = false
23
+ #
24
+ def self.emulate_booleans; DB2.emulate_booleans; end
25
+ def self.emulate_booleans=(emulate); DB2.emulate_booleans = emulate; end
26
+
27
+ ADAPTER_NAME = 'AS400'.freeze
28
+
29
+ def adapter_name
30
+ ADAPTER_NAME
31
+ end
32
+
33
+ # @override
34
+ def prefetch_primary_key?(table_name = nil)
35
+ # TRUE if the table has no identity column
36
+ names = table_name.upcase.split(".")
37
+ sql = "SELECT 1 FROM SYSIBM.SQLPRIMARYKEYS WHERE "
38
+ sql << "TABLE_SCHEM = '#{names.first}' AND " if names.size == 2
39
+ sql << "TABLE_NAME = '#{names.last}'"
40
+ select_one(sql).nil?
41
+ end
42
+
43
+ # @override
44
+ def rename_column(table_name, column_name, new_column_name)
45
+ raise NotImplementedError, "rename_column is not supported on IBM iSeries"
46
+ end
47
+
48
+ # @override
49
+ def execute_table_change(sql, table_name, name = nil)
50
+ execute_and_auto_confirm(sql, name)
51
+ end
52
+
53
+ # holy moly batman! all this to tell AS400 "yes i am sure"
54
+ def execute_and_auto_confirm(sql, name = nil)
55
+
56
+ begin
57
+ @connection.execute_update "call qsys.qcmdexc('QSYS/CHGJOB INQMSGRPY(*SYSRPYL)',0000000031.00000)"
58
+ @connection.execute_update "call qsys.qcmdexc('ADDRPYLE SEQNBR(9876) MSGID(CPA32B2) RPY(''I'')',0000000045.00000)"
59
+ rescue Exception => e
60
+ raise "Could not call CHGJOB INQMSGRPY(*SYSRPYL) and ADDRPYLE SEQNBR(9876) MSGID(CPA32B2) RPY('I').\n" +
61
+ "Do you have authority to do this?\n\n#{e.inspect}"
62
+ end
63
+
64
+ begin
65
+ result = execute(sql, name)
66
+ rescue Exception
67
+ raise
68
+ else
69
+ # Return if all work fine
70
+ result
71
+ ensure
72
+
73
+ # Ensure default configuration restoration
74
+ begin
75
+ @connection.execute_update "call qsys.qcmdexc('QSYS/CHGJOB INQMSGRPY(*DFT)',0000000027.00000)"
76
+ @connection.execute_update "call qsys.qcmdexc('RMVRPYLE SEQNBR(9876)',0000000021.00000)"
77
+ rescue Exception => e
78
+ raise "Could not call CHGJOB INQMSGRPY(*DFT) and RMVRPYLE SEQNBR(9876).\n" +
79
+ "Do you have authority to do this?\n\n#{e.inspect}"
80
+ end
81
+
82
+ end
83
+ end
84
+ private :execute_and_auto_confirm
85
+
86
+ # disable all schemas browsing when default schema is specified
87
+ def table_exists?(name)
88
+ return false unless name
89
+ schema ? @connection.table_exists?(name, schema) : @connection.table_exists?(name)
90
+ end
91
+
92
+ DRIVER_NAME = 'com.ibm.as400.access.AS400JDBCDriver'.freeze
93
+
94
+ # @private
95
+ # @deprecated no longer used
96
+ def as400?
97
+ true
98
+ end
99
+
100
+ private
101
+
102
+ # @override
103
+ def db2_schema
104
+ @db2_schema = false unless defined? @db2_schema
105
+ return @db2_schema if @db2_schema != false
106
+ @db2_schema =
107
+ if config[:schema].present?
108
+ config[:schema]
109
+ elsif config[:jndi].present?
110
+ # Only found method to set db2_schema from jndi
111
+ result = select_one("SELECT CURRENT_SCHEMA FROM SYSIBM.SYSDUMMY1")
112
+ schema = result['00001']
113
+ # If the connection uses the library list schema name will be nil
114
+ if schema == '*LIBL'
115
+ schema = nil
116
+ end
117
+ schema
118
+ else
119
+ # AS400 implementation takes schema from library name (last part of URL)
120
+ # jdbc:as400://localhost/schema;naming=system;libraries=lib1,lib2
121
+ schema = nil
122
+ split = config[:url].split('/')
123
+ # Return nil if schema isn't defined
124
+ schema = split.last.split(';').first.strip if split.size == 4
125
+ schema
126
+ end
127
+ end
128
+
129
+ end
130
+ end
@@ -0,0 +1,167 @@
1
+ module ArJdbc
2
+ module DB2
3
+
4
+ # @see ActiveRecord::ConnectionAdapters::JdbcColumn#column_types
5
+ def self.column_selector
6
+ [ /(db2|zos)/i, lambda { |config, column| column.extend(Column) } ]
7
+ end
8
+
9
+ # @see ActiveRecord::ConnectionAdapters::JdbcColumn
10
+ module Column
11
+
12
+ # @private
13
+ def self.included(base)
14
+ # NOTE: assumes a standalone DB2Column class
15
+ class << base; include Cast; end
16
+ end
17
+
18
+ # @deprecated use `self.class.string_to_time`
19
+ def self.cast_to_date_or_time(value)
20
+ return value if value.is_a? Date
21
+ return nil if value.blank?
22
+ # https://github.com/jruby/activerecord-jdbc-adapter/commit/c225126e025df2e98ba3386c67e2a5bc5e5a73e6
23
+ return Time.now if value =~ /^CURRENT/
24
+ guess_date_or_time((value.is_a? Time) ? value : cast_to_time(value))
25
+ rescue
26
+ value
27
+ end
28
+
29
+ # @deprecated use `self.class.string_to_time` or `self.class.string_to_dummy_time`
30
+ def self.cast_to_time(value)
31
+ return value if value.is_a? Time
32
+ # AS400 returns a 2 digit year, LUW returns a 4 digit year
33
+ time = DateTime.parse(value).to_time rescue nil
34
+ return nil unless time
35
+ time_array = [time.year, time.month, time.day, time.hour, time.min, time.sec]
36
+ time_array[0] ||= 2000; time_array[1] ||= 1; time_array[2] ||= 1;
37
+ Time.send(ActiveRecord::Base.default_timezone, *time_array) rescue nil
38
+ end
39
+
40
+ # @deprecated
41
+ # @private
42
+ def self.guess_date_or_time(value)
43
+ return value if value.is_a? Date
44
+ ( value && value.hour == 0 && value.min == 0 && value.sec == 0 ) ?
45
+ Date.new(value.year, value.month, value.day) : value
46
+ end
47
+
48
+ # @override
49
+ def type_cast(value)
50
+ return nil if value.nil? || value == 'NULL' || value =~ /^\s*NULL\s*$/i
51
+ case type
52
+ when :string then value
53
+ when :integer then value.respond_to?(:to_i) ? value.to_i : (value ? 1 : 0)
54
+ when :primary_key then value.respond_to?(:to_i) ? value.to_i : (value ? 1 : 0)
55
+ when :float then value.to_f
56
+ when :date then self.class.string_to_date(value)
57
+ when :datetime then self.class.string_to_time(value)
58
+ when :timestamp then self.class.string_to_time(value)
59
+ when :time then self.class.string_to_dummy_time(value)
60
+ # TODO AS400 stores binary strings in EBCDIC (CCSID 65535), need to convert back to ASCII
61
+ else
62
+ super
63
+ end
64
+ end
65
+
66
+ # @override
67
+ def type_cast_code(var_name)
68
+ case type
69
+ when :date then "#{self.class.name}.string_to_date(#{var_name})"
70
+ when :datetime then "#{self.class.name}.string_to_time(#{var_name})"
71
+ when :timestamp then "#{self.class.name}.string_to_time(#{var_name})"
72
+ when :time then "#{self.class.name}.string_to_dummy_time(#{var_name})"
73
+ else
74
+ super
75
+ end
76
+ end
77
+
78
+ private
79
+
80
+ def simplified_type(field_type)
81
+ case field_type
82
+ when /^decimal\(1\)$/i then DB2.emulate_booleans? ? :boolean : :integer
83
+ when /smallint/i then DB2.emulate_booleans? ? :boolean : :integer
84
+ when /boolean/i then :boolean
85
+ when /^real|double/i then :float
86
+ when /int|serial/i then :integer
87
+ # if a numeric column has no scale, lets treat it as an integer.
88
+ # The AS400 rpg guys do this ALOT since they have no integer datatype ...
89
+ when /decimal|numeric|decfloat/i
90
+ extract_scale(field_type) == 0 ? :integer : :decimal
91
+ when /timestamp/i then :timestamp
92
+ when /datetime/i then :datetime
93
+ when /time/i then :time
94
+ when /date/i then :date
95
+ # DB2 provides three data types to store these data objects as strings of up to 2 GB in size:
96
+ # Character large objects (CLOBs)
97
+ # Use the CLOB data type to store SBCS or mixed data, such as documents that contain
98
+ # single character set. Use this data type if your data is larger (or might grow larger)
99
+ # than the VARCHAR data type permits.
100
+ # Double-byte character large objects (DBCLOBs)
101
+ # Use the DBCLOB data type to store large amounts of DBCS data, such as documents that
102
+ # use a DBCS character set.
103
+ # Binary large objects (BLOBs)
104
+ # Use the BLOB data type to store large amounts of noncharacter data, such as pictures,
105
+ # voice, and mixed media.
106
+ when /clob|text/i then :text # handles DBCLOB
107
+ when /^long varchar/i then :text # :limit => 32700
108
+ when /blob|binary/i then :binary
109
+ # varchar () for bit data, char () for bit data, long varchar for bit data
110
+ when /for bit data/i then :binary
111
+ when /xml/i then :xml
112
+ when /graphic/i then :graphic # vargraphic, long vargraphic
113
+ when /rowid/i then :rowid # rowid is a supported datatype on z/OS and i/5
114
+ else
115
+ super
116
+ end
117
+ end
118
+
119
+ # Post process default value from JDBC into a Rails-friendly format (columns{-internal})
120
+ def default_value(value)
121
+ # IBM i (AS400) will return an empty string instead of null for no default
122
+ return nil if value.blank?
123
+
124
+ # string defaults are surrounded by single quotes
125
+ return $1 if value =~ /^'(.*)'$/
126
+
127
+ value
128
+ end
129
+
130
+ module Cast
131
+
132
+ # @override
133
+ def string_to_date(value)
134
+ return nil unless value = current_date_time_parse(value)
135
+
136
+ super
137
+ end
138
+
139
+ # @override
140
+ def string_to_time(value)
141
+ return nil unless value = current_date_time_parse(value)
142
+
143
+ super
144
+ end
145
+
146
+ # @override
147
+ def string_to_dummy_time(value)
148
+ return nil unless value = current_date_time_parse(value)
149
+
150
+ super
151
+ end
152
+
153
+ private
154
+
155
+ def current_date_time_parse(value)
156
+ return value unless value.is_a?(String)
157
+ return nil if value.empty?
158
+ return Time.now if value.index('CURRENT') == 0
159
+
160
+ return value
161
+ end
162
+
163
+ end
164
+
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,44 @@
1
+ ArJdbc::ConnectionMethods.module_eval do
2
+ # @note Assumes DB2 driver (*db2jcc.jar*) is on class-path.
3
+ def db2_connection(config)
4
+ config[:adapter_spec] ||= ::ArJdbc::DB2
5
+
6
+ return jndi_connection(config) if jndi_config?(config)
7
+
8
+ config[:url] ||= begin
9
+ if config[:host] # Type 4 URL: jdbc:db2://server:port/database
10
+ config[:port] ||= 50000
11
+ "jdbc:db2://#{config[:host]}:#{config[:port]}/#{config[:database]}"
12
+ else # Type 2 URL: jdbc:db2:database
13
+ "jdbc:db2:#{config[:database]}"
14
+ end
15
+ end
16
+ config[:driver] ||= ::ArJdbc::DB2::DRIVER_NAME
17
+ config[:connection_alive_sql] ||= 'SELECT 1 FROM syscat.tables FETCH FIRST 1 ROWS ONLY'
18
+ jdbc_connection(config)
19
+ end
20
+ alias_method :jdbcdb2_connection, :db2_connection
21
+
22
+ # @note Assumes AS400 driver (*jt400.jar*) is on class-path.
23
+ def as400_connection(config)
24
+ config[:adapter_spec] ||= ::ArJdbc::AS400
25
+
26
+ return jndi_connection(config) if config[:jndi]
27
+
28
+ config[:url] ||= begin
29
+ # jdbc:as400://[host]
30
+ url = 'jdbc:as400://'
31
+ url << config[:host] if config[:host]
32
+ # jdbc:as400://myiSeries;database name=IASP1
33
+ url << ";database name=#{config[:database]}" if config[:database]
34
+ # jdbc:as400://[host];proxy server=HODServerName:proxyServerPort
35
+ url << ";proxy server=#{config[:proxy]}" if config[:proxy]
36
+ url
37
+ end
38
+ require 'arjdbc/db2/as400'
39
+ config[:driver] ||= ::ArJdbc::AS400::DRIVER_NAME
40
+ config[:connection_alive_sql] ||= 'SELECT 1 FROM sysibm.tables FETCH FIRST 1 ROWS ONLY'
41
+ jdbc_connection(config)
42
+ end
43
+ alias_method :jdbcas400_connection, :as400_connection
44
+ end
@@ -0,0 +1,3 @@
1
+ require 'arjdbc'
2
+ require 'arjdbc/derby/connection_methods'
3
+ require 'arjdbc/derby/adapter'
@@ -0,0 +1,13 @@
1
+ # Needed because Rails is broken wrt to quoting of some values.
2
+ # Most databases are nice about it, but not Derby.
3
+ # The real issue is that you can't compare a CHAR value to a NUMBER column.
4
+ ActiveRecord::Associations::ClassMethods.module_eval do
5
+ private
6
+ def select_limited_ids_list(options, join_dependency)
7
+ return super unless connection.is_a?(ArJdbc::Derby)
8
+ connection.select_all(
9
+ construct_finder_sql_for_association_limiting(options, join_dependency),
10
+ "#{name} Load IDs For Limited Eager Loading"
11
+ ).collect { |row| connection.quote(row[primary_key], columns_hash[primary_key]) }.join(", ")
12
+ end
13
+ end
@@ -0,0 +1,540 @@
1
+ ArJdbc.load_java_part :Derby
2
+
3
+ require 'arjdbc/util/table_copier'
4
+ require 'arjdbc/derby/schema_creation' # AR 4.x
5
+ require 'arel/visitors/derby'
6
+
7
+ module ArJdbc
8
+ module Derby
9
+ include Util::TableCopier
10
+
11
+ def self.extended(adapter)
12
+ require 'arjdbc/derby/active_record_patch'
13
+ end
14
+
15
+ def self.included(base)
16
+ require 'arjdbc/derby/active_record_patch'
17
+ end
18
+
19
+ # @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_connection_class
20
+ def self.jdbc_connection_class
21
+ ::ActiveRecord::ConnectionAdapters::DerbyJdbcConnection
22
+ end
23
+
24
+ # @see ActiveRecord::ConnectionAdapters::JdbcColumn#column_types
25
+ def self.column_selector
26
+ [ /derby/i, lambda { |config, column| column.extend(Column) } ]
27
+ end
28
+
29
+ # @private
30
+ @@emulate_booleans = true
31
+
32
+ # Boolean emulation can be disabled using :
33
+ #
34
+ # ArJdbc::Derby.emulate_booleans = false
35
+ #
36
+ def self.emulate_booleans?; @@emulate_booleans; end
37
+ # @deprecated Use {#emulate_booleans?} instead.
38
+ def self.emulate_booleans; @@emulate_booleans; end
39
+ # @see #emulate_booleans?
40
+ def self.emulate_booleans=(emulate); @@emulate_booleans = emulate; end
41
+
42
+ # @note Part of this module is implemented in "native" Java.
43
+ # @see ActiveRecord::ConnectionAdapters::JdbcColumn
44
+ module Column
45
+
46
+ private
47
+
48
+ def extract_limit(sql_type)
49
+ case @sql_type = sql_type.downcase
50
+ when /^smallint/i then @sql_type = 'smallint'; limit = 2
51
+ when /^bigint/i then @sql_type = 'bigint'; limit = 8
52
+ when /^double/i then @sql_type = 'double'; limit = 8 # DOUBLE PRECISION
53
+ when /^real/i then @sql_type = 'real'; limit = 4
54
+ when /^integer/i then @sql_type = 'integer'; limit = 4
55
+ when /^datetime/i then @sql_type = 'datetime'; limit = nil
56
+ when /^timestamp/i then @sql_type = 'timestamp'; limit = nil
57
+ when /^time/i then @sql_type = 'time'; limit = nil
58
+ when /^date/i then @sql_type = 'date'; limit = nil
59
+ when /^xml/i then @sql_type = 'xml'; limit = nil
60
+ else
61
+ limit = super
62
+ # handle maximum length for a VARCHAR string :
63
+ limit = 32672 if ! limit && @sql_type.index('varchar') == 0
64
+ end
65
+ limit
66
+ end
67
+
68
+ def simplified_type(field_type)
69
+ case field_type
70
+ when /^smallint/i then Derby.emulate_booleans? ? :boolean : :integer
71
+ when /^bigint|int/i then :integer
72
+ when /^real|double/i then :float
73
+ when /^dec/i then # DEC is a DECIMAL alias
74
+ extract_scale(field_type) == 0 ? :integer : :decimal
75
+ when /^timestamp/i then :datetime
76
+ when /^xml/i then :xml
77
+ when 'long varchar' then :text
78
+ when /for bit data/i then :binary
79
+ # :name=>"long varchar for bit data", :limit=>32700
80
+ # :name=>"varchar() for bit data", :limit=>32672
81
+ # :name=>"char() for bit data", :limit=>254}
82
+ else
83
+ super
84
+ end
85
+ end
86
+
87
+ # Post process default value from JDBC into a Rails-friendly format (columns{-internal})
88
+ def default_value(value)
89
+ # JDBC returns column default strings with actual single quotes around the value.
90
+ return $1 if value =~ /^'(.*)'$/
91
+ return nil if value == "GENERATED_BY_DEFAULT"
92
+ value
93
+ end
94
+
95
+ end
96
+
97
+ ADAPTER_NAME = 'Derby'.freeze
98
+
99
+ def adapter_name
100
+ ADAPTER_NAME
101
+ end
102
+
103
+ def configure_connection
104
+ # must be done or SELECT...FOR UPDATE won't work how we expect :
105
+ if tx_isolation = config[:transaction_isolation]
106
+ @connection.transaction_isolation = tx_isolation
107
+ end
108
+ # if a user name was specified upon connection, the user's name is the
109
+ # default schema for the connection, if a schema with that name exists
110
+ set_schema(config[:schema]) if config[:schema]
111
+ end
112
+
113
+ def index_name_length
114
+ 128
115
+ end
116
+
117
+ NATIVE_DATABASE_TYPES = {
118
+ :primary_key => "int GENERATED BY DEFAULT AS identity NOT NULL PRIMARY KEY",
119
+ :string => { :name => "varchar", :limit => 255 }, # 32672
120
+ :text => { :name => "clob" }, # 2,147,483,647
121
+ :char => { :name => "char", :limit => 254 }, # JDBC :limit => 254
122
+ :binary => { :name => "blob" }, # 2,147,483,647
123
+ :float => { :name => "float", :limit => 8 }, # DOUBLE PRECISION
124
+ :real => { :name => "real", :limit => 4 }, # JDBC :limit => 23
125
+ :double => { :name => "double", :limit => 8 }, # JDBC :limit => 52
126
+ :decimal => { :name => "decimal", :precision => 5, :scale => 0 }, # JDBC :limit => 31
127
+ :numeric => { :name => "decimal", :precision => 5, :scale => 0 }, # JDBC :limit => 31
128
+ :integer => { :name => "integer", :limit => 4 }, # JDBC :limit => 10
129
+ :smallint => { :name => "smallint", :limit => 2 }, # JDBC :limit => 5
130
+ :bigint => { :name => "bigint", :limit => 8 }, # JDBC :limit => 19
131
+ :date => { :name => "date" },
132
+ :time => { :name => "time" },
133
+ :datetime => { :name => "timestamp" },
134
+ :timestamp => { :name => "timestamp" },
135
+ :xml => { :name => "xml" },
136
+ :boolean => { :name => "smallint", :limit => 1 }, # TODO boolean (since 10.7)
137
+ :object => { :name => "object" },
138
+ }
139
+
140
+ # @private
141
+ def initialize_type_map(m)
142
+ super
143
+ m.register_type(%r(smallint)i) do |sql_type|
144
+ if Derby.emulate_booleans?
145
+ ActiveRecord::Type::Boolean.new
146
+ else
147
+ ActiveRecord::Type::Integer.new(:limit => 1)
148
+ end
149
+ end
150
+ m.alias_type %r(real)i, 'float'
151
+ end if AR42
152
+
153
+ def reset_column_information
154
+ initialize_type_map(type_map)
155
+ end if AR42
156
+
157
+ # @override
158
+ def native_database_types
159
+ NATIVE_DATABASE_TYPES
160
+ end
161
+
162
+ # UNTESTED
163
+ def existing_savepoint_name?(name)
164
+ (@connection.instance_variable_get('@savepoints') || {}).key? name
165
+ end
166
+
167
+ # Ensure the savepoint name is unused before creating it.
168
+ # @override
169
+ def create_savepoint(name = current_savepoint_name(true))
170
+ release_savepoint(name) if existing_savepoint_name?(name)
171
+ super(name)
172
+ end
173
+
174
+ # @override
175
+ def quote(value, column = nil)
176
+ return super if column && ArJdbc::AR42 && column.cast_type.is_a?(ActiveRecord::Type::Serialized)
177
+ return value.quoted_id if value.respond_to?(:quoted_id)
178
+ return value if sql_literal?(value)
179
+ return 'NULL' if value.nil?
180
+
181
+ column_type = column && column.type
182
+ if column_type == :string || column_type == :text
183
+ # Derby is not permissive
184
+ # e.g. sending an Integer to a VARCHAR column will fail
185
+ case value
186
+ when BigDecimal then value = value.to_s('F')
187
+ when Numeric then value = value.to_s
188
+ when true, false then value = value.to_s
189
+ when Date, Time then value = quoted_date(value)
190
+ else # on 2.3 attribute serialization needs to_yaml here
191
+ value = value.to_s if ActiveRecord::VERSION::MAJOR >= 3
192
+ end
193
+ end
194
+
195
+ case value
196
+ when String, ActiveSupport::Multibyte::Chars
197
+ if column_type == :text
198
+ "CAST('#{quote_string(value)}' AS CLOB)"
199
+ elsif column_type == :binary
200
+ "CAST(X'#{quote_binary(value)}' AS BLOB)"
201
+ elsif column_type == :xml
202
+ "XMLPARSE(DOCUMENT '#{quote_string(value)}' PRESERVE WHITESPACE)"
203
+ elsif column_type == :integer
204
+ value.to_i
205
+ elsif column_type == :float
206
+ value.to_f
207
+ else
208
+ "'#{quote_string(value)}'"
209
+ end
210
+ else
211
+ super
212
+ end
213
+ end
214
+
215
+ # @override
216
+ def quoted_date(value)
217
+ if value.acts_like?(:time) && value.respond_to?(:usec)
218
+ usec = sprintf("%06d", value.usec)
219
+ value = ::ActiveRecord::Base.default_timezone == :utc ? value.getutc : value.getlocal
220
+ "#{value.strftime("%Y-%m-%d %H:%M:%S")}.#{usec}"
221
+ else
222
+ super
223
+ end
224
+ end if ::ActiveRecord::VERSION::MAJOR >= 3
225
+
226
+ # @private In Derby, these cannot specify a limit.
227
+ NO_LIMIT_TYPES = [ :integer, :boolean, :timestamp, :datetime, :date, :time ]
228
+
229
+ # Convert the specified column type to a SQL string.
230
+ # @override
231
+ def type_to_sql(type, limit = nil, precision = nil, scale = nil)
232
+ return super unless NO_LIMIT_TYPES.include?(t = type.to_s.downcase.to_sym)
233
+
234
+ native_type = NATIVE_DATABASE_TYPES[t]
235
+ native_type.is_a?(Hash) ? native_type[:name] : native_type
236
+ end
237
+
238
+ # @private
239
+ class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
240
+
241
+ def xml(*args)
242
+ options = args.extract_options!
243
+ column(args[0], 'xml', options)
244
+ end
245
+
246
+ end
247
+
248
+ def table_definition(*args)
249
+ new_table_definition(TableDefinition, *args)
250
+ end
251
+
252
+ # @override
253
+ def empty_insert_statement_value
254
+ ::Arel::Visitors::Derby::VALUES_DEFAULT # Derby needs to know the columns
255
+ end
256
+
257
+ # Set the sequence to the max value of the table's column.
258
+ # @override
259
+ def reset_sequence!(table, column, sequence = nil)
260
+ mpk = select_value("SELECT MAX(#{quote_column_name(column)}) FROM #{quote_table_name(table)}")
261
+ execute("ALTER TABLE #{quote_table_name(table)} ALTER COLUMN #{quote_column_name(column)} RESTART WITH #{mpk.to_i + 1}")
262
+ end
263
+
264
+ def reset_pk_sequence!(table, pk = nil, sequence = nil)
265
+ klasses = classes_for_table_name(table)
266
+ klass = klasses.nil? ? nil : klasses.first
267
+ pk = klass.primary_key unless klass.nil?
268
+ if pk && klass.columns_hash[pk].type == :integer
269
+ reset_sequence!(klass.table_name, pk)
270
+ end
271
+ end
272
+
273
+ def classes_for_table_name(table)
274
+ ActiveRecord::Base.send(:subclasses).select { |klass| klass.table_name == table }
275
+ end
276
+ private :classes_for_table_name
277
+
278
+ # @override
279
+ def remove_index(table_name, options)
280
+ execute "DROP INDEX #{index_name(table_name, options)}"
281
+ end
282
+
283
+ # @override
284
+ def rename_table(name, new_name)
285
+ execute "RENAME TABLE #{quote_table_name(name)} TO #{quote_table_name(new_name)}"
286
+ end
287
+
288
+ def add_column(table_name, column_name, type, options = {})
289
+ add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
290
+ add_column_options!(add_column_sql, options)
291
+ execute(add_column_sql)
292
+ end unless const_defined? :SchemaCreation
293
+
294
+ # @override fix case where AR passes `:default => nil, :null => true`
295
+ def add_column_options!(sql, options)
296
+ options.delete(:default) if options.has_key?(:default) && options[:default].nil?
297
+ sql << " DEFAULT #{quote(options.delete(:default))}" if options.has_key?(:default)
298
+ super
299
+ end unless const_defined? :SchemaCreation
300
+
301
+ if ActiveRecord::VERSION::MAJOR >= 4
302
+
303
+ # @override
304
+ def remove_column(table_name, column_name, type = nil, options = {})
305
+ do_remove_column(table_name, column_name)
306
+ end
307
+
308
+ else
309
+
310
+ # @override
311
+ def remove_column(table_name, *column_names)
312
+ for column_name in column_names.flatten
313
+ do_remove_column(table_name, column_name)
314
+ end
315
+ end
316
+ alias remove_columns remove_column
317
+
318
+ end
319
+
320
+ def do_remove_column(table_name, column_name)
321
+ execute "ALTER TABLE #{quote_table_name(table_name)} DROP COLUMN #{quote_column_name(column_name)} RESTRICT"
322
+ end
323
+ private :do_remove_column
324
+
325
+ # @override
326
+ def change_column(table_name, column_name, type, options = {})
327
+ # TODO this needs a review since now we're likely to be on >= 10.8
328
+
329
+ # Notes about changing in Derby:
330
+ # http://db.apache.org/derby/docs/10.2/ref/rrefsqlj81859.html#rrefsqlj81859__rrefsqlj37860)
331
+ #
332
+ # We support changing columns using the strategy outlined in:
333
+ # https://issues.apache.org/jira/browse/DERBY-1515
334
+ #
335
+ # This feature has not made it into a formal release and is not in Java 6.
336
+ # We will need to conditionally support this (supposed to arrive for 10.3.0.0).
337
+
338
+ # null/not nulling is easy, handle that separately
339
+ if options.include?(:null)
340
+ # This seems to only work with 10.2 of Derby
341
+ if options.delete(:null) == false
342
+ execute "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} NOT NULL"
343
+ else
344
+ execute "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} NULL"
345
+ end
346
+ end
347
+
348
+ # anything left to do?
349
+ unless options.empty?
350
+ begin
351
+ execute "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN " <<
352
+ " #{quote_column_name(column_name)} SET DATA TYPE #{type_to_sql(type, options[:limit])}"
353
+ rescue
354
+ transaction do
355
+ temp_new_column_name = "#{column_name}_newtype"
356
+ # 1) ALTER TABLE t ADD COLUMN c1_newtype NEWTYPE;
357
+ add_column table_name, temp_new_column_name, type, options
358
+ # 2) UPDATE t SET c1_newtype = c1;
359
+ execute "UPDATE #{quote_table_name(table_name)} SET " <<
360
+ " #{quote_column_name(temp_new_column_name)} = " <<
361
+ " CAST(#{quote_column_name(column_name)} AS #{type_to_sql(type, options[:limit])})"
362
+ # 3) ALTER TABLE t DROP COLUMN c1;
363
+ remove_column table_name, column_name
364
+ # 4) ALTER TABLE t RENAME COLUMN c1_newtype to c1;
365
+ rename_column table_name, temp_new_column_name, column_name
366
+ end
367
+ end
368
+ end
369
+ end
370
+
371
+ # @override
372
+ def rename_column(table_name, column_name, new_column_name)
373
+ execute "RENAME COLUMN #{quote_table_name(table_name)}.#{quote_column_name(column_name)} " <<
374
+ " TO #{quote_column_name(new_column_name)}"
375
+ end
376
+
377
+ # SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause.
378
+ #
379
+ # Derby requires the ORDER BY columns in the select list for distinct queries, and
380
+ # requires that the ORDER BY include the distinct column.
381
+ # ```
382
+ # distinct("posts.id", "posts.created_at desc")
383
+ # ```
384
+ # @note This is based on distinct method for the PostgreSQL Adapter.
385
+ # @override
386
+ def distinct(columns, order_by)
387
+ "DISTINCT #{columns_for_distinct(columns, order_by)}"
388
+ end
389
+
390
+ # @override Since AR 4.0 (on 4.1 {#distinct} is gone and won't be called).
391
+ def columns_for_distinct(columns, orders)
392
+ return columns if orders.blank?
393
+
394
+ # construct a clean list of column names from the ORDER BY clause,
395
+ # removing any ASC/DESC modifiers
396
+ order_columns = [ orders ]; order_columns.flatten! # AR 3.x vs 4.x
397
+ order_columns.map! do |column|
398
+ column = column.to_sql unless column.is_a?(String) # handle AREL node
399
+ column.split(',').collect! { |s| s.split.first }
400
+ end.flatten!
401
+ order_columns.reject!(&:blank?)
402
+ order_columns = order_columns.zip (0...order_columns.size).to_a
403
+ order_columns = order_columns.map { |s, i| "#{s} AS alias_#{i}" }
404
+
405
+ columns = [ columns ]; columns.flatten!
406
+ columns.push( *order_columns ).join(', ')
407
+ # return a DISTINCT clause that's distinct on the columns we want but
408
+ # includes all the required columns for the ORDER BY to work properly
409
+ end
410
+
411
+ # @override
412
+ def primary_keys(table_name)
413
+ @connection.primary_keys table_name.to_s.upcase
414
+ end
415
+
416
+ # @override
417
+ def tables(name = nil)
418
+ @connection.tables(nil, current_schema)
419
+ end
420
+
421
+ # @override
422
+ def supports_ddl_transactions?; true end
423
+
424
+ # @override
425
+ def supports_foreign_keys?; true end
426
+
427
+ def truncate(table_name, name = nil)
428
+ execute "TRUNCATE TABLE #{quote_table_name(table_name)}", name
429
+ end
430
+
431
+ # @return [String] the current schema name
432
+ def current_schema
433
+ @current_schema ||=
434
+ select_value "SELECT CURRENT SCHEMA FROM SYS.SYSSCHEMAS FETCH FIRST 1 ROWS ONLY", 'SCHEMA'
435
+ end
436
+
437
+ # Change the current (implicit) Derby schema to be used for this connection.
438
+ def set_schema(schema)
439
+ @current_schema = nil
440
+ execute "SET SCHEMA #{schema}", 'SCHEMA'
441
+ end
442
+ alias_method :current_schema=, :set_schema
443
+
444
+ # Creates a new Derby schema.
445
+ # @see #set_schema
446
+ def create_schema(schema)
447
+ execute "CREATE SCHEMA #{schema}", 'Create Schema'
448
+ end
449
+
450
+ # Drops an existing schema, needs to be empty (no DB objects).
451
+ def drop_schema(schema)
452
+ execute "DROP SCHEMA #{schema} RESTRICT", 'Drop Schema'
453
+ end
454
+
455
+ # @private
456
+ def recreate_database(name = nil, options = {})
457
+ drop_database(name)
458
+ create_database(name, options)
459
+ end
460
+
461
+ # @private
462
+ def create_database(name = nil, options = {}); end
463
+
464
+ # @private
465
+ def drop_database(name = nil)
466
+ tables.each { |table| drop_table(table) }
467
+ end
468
+
469
+ # @override
470
+ def quote_column_name(name)
471
+ %Q{"#{name.to_s.upcase.gsub('"', '""')}"}
472
+ end
473
+
474
+ # @override
475
+ def quote_table_name_for_assignment(table, attr)
476
+ quote_column_name(attr)
477
+ end if ::ActiveRecord::VERSION::MAJOR > 3
478
+
479
+ # @note Only used with (non-AREL) ActiveRecord **2.3**.
480
+ # @see Arel::Visitors::Derby
481
+ def add_limit_offset!(sql, options)
482
+ sql << " OFFSET #{options[:offset]} ROWS" if options[:offset]
483
+ # ROWS/ROW and FIRST/NEXT mean the same
484
+ sql << " FETCH FIRST #{options[:limit]} ROWS ONLY" if options[:limit]
485
+ end if ::ActiveRecord::VERSION::MAJOR < 3
486
+
487
+ # @override
488
+ def execute(sql, name = nil, binds = [])
489
+ sql = to_sql(sql, binds)
490
+ insert = self.class.insert?(sql)
491
+ update = ! insert && ! self.class.select?(sql)
492
+ sql = correct_is_null(sql, insert || update)
493
+ super(sql, name, binds)
494
+ end
495
+
496
+ # Returns the value of an identity column of the last *INSERT* statement
497
+ # made over this connection.
498
+ # @note Check the *IDENTITY_VAL_LOCAL* function for documentation.
499
+ # @return [Fixnum]
500
+ def last_insert_id
501
+ @connection.identity_val_local
502
+ end
503
+
504
+ private
505
+
506
+ def correct_is_null(sql, insert_or_update = false)
507
+ if insert_or_update
508
+ if ( i = sql =~ /\sWHERE\s/im )
509
+ where_part = sql[i..-1]; sql = sql.dup
510
+ where_part.gsub!(/!=\s*NULL/i, 'IS NOT NULL')
511
+ where_part.gsub!(/=\sNULL/i, 'IS NULL')
512
+ sql[i..-1] = where_part
513
+ end
514
+ sql
515
+ else
516
+ sql.gsub(/=\sNULL/i, 'IS NULL')
517
+ end
518
+ end
519
+
520
+ # NOTE: only setup query analysis on AR <= 3.0 since on 3.1 {#exec_query},
521
+ # {#exec_insert} will be used for AR generated queries/inserts etc.
522
+ # Also there's prepared statement support and {#execute} is meant to stay
523
+ # as a way of running non-prepared SQL statements (returning raw results).
524
+ if ActiveRecord::VERSION::MAJOR < 3 ||
525
+ ( ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR < 1 )
526
+
527
+ def _execute(sql, name = nil)
528
+ if self.class.insert?(sql)
529
+ @connection.execute_insert(sql)
530
+ elsif self.class.select?(sql)
531
+ @connection.execute_query_raw(sql)
532
+ else
533
+ @connection.execute_update(sql)
534
+ end
535
+ end
536
+
537
+ end
538
+
539
+ end
540
+ end